c
```<080223
C file-name               GXBLIN.HTM             200623
c-->
C!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
C-------------------------------------------------------------------------
SUBROUTINE GXBLIN
C-------------------------------------------------------------------------
C
C     PHOENICS V2020
C     Author:  M.R.Malin / J C Ludwig
C     Date:    24/09/04 - 16/04/20
C
C     Subroutine GXBLIN is called from Group 1 Section 1 and Group 13 Section
C     19 of GREX3 {using the logical condition IF(NPATCH(1:4=='BLIN')}.
C
C     The purpose of this subroutine is to set mass-flow boundary
C     conditions for the momentum and k-e (or k-f) equations so as to
C     define a boundary-layer profile at domain boundaries. At present an
C     option is provided only for a neutral atmospheric boundary layer
C     (wind profile) using either a logarithmic or power-law velocity
C     profile, as follows:
C
C          Q = {QTAU/Kappa}*ln((z-d)/zo)  or   Q = Qref*(z/zref)^a
C
C          k = QTAU^2/sqrt(cmucd)
C
C          e = QTAU^3/(K*[z-d]) or  f =  QTAU/(Kappa*sqrt(cmucd)*(z-d))
C
C     where the friction velocity QTAU is given by:
C
C          Q*= Qref*K/log([zref-d]/zo)
C
C     and
C
C     Kappa = 0.41, zo is the effective roughness height of the ground terrain,
C     z is the displacement height, Qref is the reference velocity at the
C     reference height zref, a is the power-law exponent, z is the vertical
C     coordinate, and Q is the velocity at the height z from the ground.
C
C     The displacement height d is a positive quantity, although the user
C     can set d=-z0 to create the inlet wind profiles proposed by Richards
C     & Hoxey (1993), which are often used in wind-engineering simulations.
C     ( see Richards,P.J. & Hoxey,R.P., "Appropriate boundary conditions for
C     computational wind engineering models using the k-e turbulence model."
C     J.Wind Engng & Industrial Aerodynamics, 46 & 47, 145-153, (1993) ).
C
C
C     The vertical coordinate is taken to start at the lower edge of the first
C     cut or fully-open cell in each column of an inlet plane.
C
C     The facility requires that the user defines a PATCH whose name starts
C     with the 4 characters BLIN at the inlet boundary, such as for example:
C
C   PATCH(BLIN1,LOW,1,NX,1,NY,1,1,1,1)
C   COVAL(BLIN1,P1,FIXFLU, GRND7)
C   COVAL(BLIN1,U1,0.0   , GRND7)
C   COVAL(BLIN1,V1,0.0   , GRND7)
C   COVAL(BLIN1,W1,0.0   , GRND7)
C   COVAL(BLIN1,KE,0.0   , GRND7)
C   COVAL(BLIN1,EP,0.0   , GRND7) or COVAL(BLIN1,OMEG,0.0   , GRND7)
C   COVAL(BLIN1,TEM1,0.0 , GRND7)
C
C     In addition, the following SPEDAT statements must be set in the Q1
C     input file:
C
C   SPEDAT(SET,BLIN1,VELX,R,Wx)   : x-component of Qref
C   SPEDAT(SET,BLIN1,VELY,R,Wy)   : y-component of Qref
C   SPEDAT(SET,BLIN1,VELZ,R,Wz)   : z-component of Qref
C   SPEDAT(SET,BLIN1,TAIR,R,Tair) : Air temperature
C
C   SPEDAT(SET,BLIN1,VDIR,C,Y)     : vertical coordinate direction
C   SPEDAT(SET,BLIN1,RHOIN,R,1.189): inlet density presumed uniform
C   SPEDAT(SET,BLIN1,BLTY,C,LOGL)  : profile type, i.e. LOGL, POWL or TABLE
C   SPEDAT(SET,BLIN1,ZO,R,2.0E-02) : effective roughness height
C   SPEDAT(SET,BLIN1,REFH,R,10.0)  : ref. height for ref. velocity
C   SPEDAT(SET,BLIN1,ALPHA,R,0.21) : power-law index for power-law profile
C   SPEDAT(SET,BLIN,U-TABLE,C,file_name) : name of velocity profile table for
C                                          tabular profile
C   SPEDAT(SET,BLIN,K-TABLE,C,file_name) : name of turbulent kinetic energy
C                                          profile table for tabular profile
C
C   NOTE: for tabular profiles, it is the user's resposibility to ensure that
C         the tables cover the entire height of the domain. If any cells are
C         found below the lowest point in the table or above the highest point
C         in the table, the first or last values will be used. In between,
C         linear interpolation will be used to obtain values at the local height
C         above the terrain. It is the user's responsibility to ensure that
C         the roughness height used in the fully-rough wall function is consistent
C         with the velocity and turbulent kinetic energy profiles.
C
C         The table should contain a header line (giving the titles of the columns)
C         followed by pairs of values in free format with blank or comma as
C         separators. The first value is the height, the second is the velocity or
C         turbulent kinetic energy. The two tables do not have to contain the same
C         number of data points.
C
C   The PIL variable WALLB is used for the displacement height.
C
C   To calculate external values at fixed pressure boundaries, the COVAL for P1
C   can be replaced with a normal pressure boundary condition:
C   COVAL(BLIN1,P1,COef, 0.0)
C   Note that the external pressure is always kept at zero relative to pRESS), and
C   PRESS0 is updated to the current atmospheric pressure.
C
C   In order for the BLIN patch to automatically detect inflow/outflow based
C   on wind direction and switch between fixed mass flow and fixed pressure
C   the COVAL for P1 should be:
C   COVAL(BLIN1,P1,GRND8, GRND7)
C
C   At the SKY boundary, in addition to the fixed pressure condition, the diffusive
C   vertical link can be introduced by using GRND7 as the COefficient for velocities
C   and turbulence variables. The SKY patch is recognised because it is normal to
C   the vertical coordinate direction.
C   COVAL(BLIN1,P1,   COef,  Pext)
C   COVAL(BLIN1,U1,  GRND7, GRND7)
C   COVAL(BLIN1,V1,  GRND7, GRND7)
C   COVAL(BLIN1,W1,    0.0,   0.0) [the vertical component does not need a COVAL]
C   COVAL(BLIN1,KE,  GRND7, GRND7)
C   COVAL(BLIN1,EP,  GRND7, GRND7)  or COVAL(BLIN1,OMEG,  GRND7, GRND7)
C   COVAL(BLIN1,TEM1,GRND7, GRND7)
C
C   The transient variation of wind speed, direction and air temperature may be taken
C   from  a weather data file in EPW format. In this case, the name of the data file
C   is passed as:
C     SPEDAT(SET,'BLIN','WEATHERFILE',C,filename)
C
C   The data required for the current run will have been extracted from the weather file
C   by the pre-processor. The number of lines of data sent is set as:
C     SPEDAT(SET,'BLIN','NLINES',I,nlines)
C
C   The number of entries per hour (defaulted to 1) is set by:
C     SPEDAT(SET,'BLIN','NPHOUR',I,nphour)
C
C   Each line of data contains the wind speed, wind direction and temperature
C     SPEDAT(SET,'BLIN','LINEn',C, wspeed,wdir,wtemp)
C
C   The direction of the domain relative to North must also be specified as
C     SPEDAT(SET,'BLIN','AXDIR',R,axdir)
C   where axdir is the angle between Y and North (for up Z)
C
C   As an alternative to using a weather file, multiple WIND objects can be specified
C   in a transient. The start and end times must be set to prevent overlap.
C
C   If STORE(WAMP) appears in the Q1, the wind amplification factor, defined
C   as absolute velocity / wind speed at 1.5m, will be calculated and placed in WAMP.
C   If VABS has been stored, that will be used for the absolute velocity. If it
C   is not stored, the absolute velocity will be calculated locally. The reference
C   height for WAMP can be changed using the following spedat:
C     SPEDAT(SET,'BLIN','WAMPH',R,wamph)
C   If the line is absent, a height of 1.5m will be assumed.
C
C   Pasquill Stability-Class Inlet Profiles
C
C   Class-F profiles
C       Q = (QTAU/Kappa)*(ln((z-d)/zo) - PSIU)
C       T = To - (g/Cp)*(Z-ZTo) + (T*/kappa)*(ln((z-d)/zo) - PSIT)
C       k = {QTAU^2/sqrt(cmucd)} * SQRT(1. - ZETA/PHI)
C       e = {QTAU^3/(K*[z-d])} *PHI*(1.-ZETA/PHI) or
C       f = {QTAU/(Kappa*sqrt(cmucd)*(z-d))} * PHI
C
C   where PSIU = -5*z/LMO           Monin-Obukhov (MO) Similarity parameter
C         PSIT = -5*z/LMO           MO Similarity parameter for heat
C         PHI  = 1. + 5*z/LMO       MO Similarity parameter for turbulence
C         LMO  =                    MO length scale
C         T*   =  -Qw/(rho*Cp*QTAU) Friction temperature
C
C   This facility requires the following SPEDAT statements to be set in the Q1
C   input file:
C   SPEDAT(SET,BLIN,MOLEN,I,MOLEN) : MOLEN = 0 User-specified Monin-Obukhov length
C                                          = 1 TNO formulae
C                                          = 2 PHAST formulae
C   SPEDAT(SET,BLIN,ITPRO,I,ITPRO) : ITPRO = 0 No Pasquill profile, so neutral
C                                          = 1 Class A: Very unstable  (LMO<0)
C                                          = 2 Class B: Moderately unstable (LMO<0)
C                                          = 3 Class C: Slightly unstable   (LMO<0)
C                                          = 4 Class D: Neutral             (LMO=0)
C                                          = 5 Class E: Slightly stable     (LMO>0)
C                                          = 6 Class F: Moderately stable   (LMO>0)
C
C    Nb: ITPRO=4 is neutral with a uniform temperature profile, although this may be used
C        in the future to code a neutral logarithmic temperature profile.
C
C   SPEDAT(SET,BLIN1,GT0  ,R,To)  : T0
C   SPEDAT(SET,BLIN1,GTZ0 ,R,ZTo) : Z height for T0
C   SPEDAT(SET,BLIN1,QWALL,R,Qw)  : heat flux (computed in pre-processor for terrain heat flux)
C
C     Limitations:
C     No provision has been made as yet for scalar profiles, and the logarithmic
C     profile is restricted to the fully-rough wall law, as encountered in the
C     atmospheric boundary layer. At present, the GXBLIN facility cannot be used
C     for BFC=T, GCV=T or CCM=T.
C
C------------------------------------------------------------------------
USE weather_data
INCLUDE 'farray'
INCLUDE 'patnos'
INCLUDE 'parallel'
INCLUDE 'objnam'
INCLUDE 'd_earth/parvar'
INCLUDE 'patcmn'
INCLUDE 'satear'
INCLUDE 'grdloc'
INCLUDE 'satgrd'
INCLUDE 'grdear'
INCLUDE 'grdbfc'
INCLUDE 'd_earth/pbcstr'
common/topinf/topid,idx,idy,idz
common/comlnk/llnk,hlnk,slnk,nlnk,elnk,wlnk
integer topid,llnk,hlnk,slnk,nlnk,elnk,wlnk
INCLUDE 'parear'
common/wdomin/nxsd,nysd,nzsd
COMMON /INTDMN/IDMN,NUMDMN,NXMAX,NYMAX,NZMAX,NXYMAX,NXYZMX,NCLTOT,
1               NDOMMX
COMMON/GENI/NXNY,IGFIL1(8),NFM,IGF(21),IPRL,IBTAU,ILTLS,IGFIL(15),
COMMON/DRHODP/ITEMP,IDEN/DVMOD/IDVCGR
COMMON/NAMFN/NAMFUN,NAMSUB
CHARACTER*6 NAMFUN,NAMSUB
COMMON /FACES/L0FACE,L0FACZ
COMMON /WORDI1/ NWDS,NCHARS(20),NSEMI,H,NLINES
INTEGER   H
COMMON /WORDL1/ ERROR,MORWDS
COMMON /WORDC1/ WD(20),INLINE
LOGICAL         ERROR,MORWDS
CHARACTER       WD*20, INLINE*120,CH1*13,CH2*13,CHGR_13*13,DELIM*1
COMMON/TSKEMI/ LBKP,LBKT,LBET,LBVOSQ,LBOMEG
COMMON/LRNTM4/RSCMCD,CDDAK2,TAUDKE,RTTDKE,AKC,EWC
COMMON/KWMOD3/CWWALL,SIGK1,SIGK2,SIGW1,SIGW2,CWA1,CWA2,CWB1,CWB2,
1              BETAST,CDSIG
COMMON/KWMOD1/LBKWF1(7),LBBF1,LBBF2,LBBF3,LBSIGK,LBSIGW,LBKWF2(5)
COMMON/RHILO/HI3D,RLO3D
COMMON/IHILO/IXHI3D,IYHI3D,IZHI3D,IXLO3D,IYLO3D,IZLO3D,IMAXC(150)
COMMON/PASQLF/ITPRO,PASQBUOY,BUOSSG,MOLEN
LOGICAL PASQBUOY,BUOSSG
1        LWP,SWP,WWP,LTZ,SHOWCOMF,WEICOEF,NEN,LPAR,LAWS,NEZ,
1        LGWC
CHARACTER*14 CTEMP*8,BLTY*5,VDIR*1,LINE*256,CVAL*68,SITENAME*68
CHARACTER*8 TYPECOMF,WINDFILE*256,TERRNAM*12,COBNM2*12,
1            VELFILE*256,KEFILE*256,DLIM*4
CHARACTER   PASQUILL*16
PARAMETER (MAXDMN = 10)
INTEGER L0IPAT(MAXDMN),L0VELX(MAXDMN),L0VELY(MAXDMN),
1        L0VELZ(MAXDMN),L0QREF(MAXDMN),L0VDIR(MAXDMN),
1        L0ZREF(MAXDMN),L0HREF(MAXDMN),L0BLTY(MAXDMN),
1        L0DENS(MAXDMN),L0POWR(MAXDMN),L0H,
1        NBLIN(MAXDMN), L0SKY(MAXDMN),L0TAIR(MAXDMN),
1        L0PCOE(MAXDMN),L0PVAL(MAXDMN),L0RELH(MAXDMN),
1        L0WMP(MAXDMN),L0HIWAF(MAXDMN),L0VAB(MAXDMN)
REAL, ALLOCATABLE :: BUFF(:)
INTEGER, ALLOCATABLE :: L0HI(:,:)
REAL, ALLOCATABLE :: WNDA(:,:),VEL_TAB(:,:), KE_TAB(:,:)
REAL NORML(3)
REAL, ALLOCATABLE :: LTHRESH(:), LUTHR(:),LPRO(:,:)
REAL THRESHD(7),UTHRD(7)
LOGICAL*4 EXISTS
COMMON/IPRB/LBPRB1,LBPRB2,LBPRB3,LBPRB4,LBPRB5,LBPRB6,
1            L0PRB1,L0PRB2,L0PRB3,L0PRB4,L0PRB5,L0PRB6
INTEGER LBPRB(6),L0PRB(6)
EQUIVALENCE(LBPRB(1),LBPRB1),(L0PRB(1),L0PRB1)
SAVE L0IPAT,L0VELX,L0VELY,L0VELZ,L0QREF,L0VDIR,L0ZREF,L0HREF,
1     L0BLTY,L0DENS,L0POWR,L0HI,L0H,NBLIN,L0SKY,NL,L0TAIR,
1     L0PCOE,L0PVAL,L0RELH,IFLO,IHUM,IHUNIT,LBWAMP,LBVABS,
1     IBLIN,INIBUOY,LBCP,LBPRO,LBDAN,LBNEN,ISECT,NBINS,L0WMP,
1     L0WAMP,LBWAF,L0HIWAF,IERR1,IERR2,LBVAV,L0VAB,
1     NLINEV,NLINEK,LBLAWS,NCRIT,LBWAT,LBRHIN,LBTREF,L0TREF0,
1     L0PIN0,L0RHIN0,LBPIN
SAVE AXDIR, RHOIN,WAMPVR, WMAST,WNDA,UTHR,DTHR,SECTP,VSECT,
1     AW,AKW, WDIRN, ANG, GT0,GZT0,GALR,GQWALL,GLMO
SAVE LTHRESH,LUTHR,LPRO
SAVE SHOWCOMF,WEICOEF,NEN,LAWS
SAVE TYPECOMF
SAVE VEL_TAB, KE_TAB, DLIM, VDIR
DATA THRESHD /0.06, 0.02, 0.04, 0.06, 0.01,0.0, 0.0 /
DATA UTHRD /10.95, 10.95, 8.25, 5.6, 5.6, 0.0, 0.0 /
c***********************************************************************
c
IF(USP) RETURN
IXL=IABS(IXL)
NAMSUB='GXBLIN'; NAMFUN=' '
C*****************************************************************
C--- GROUP 1. Preliminaries
IF(IGR==1)  THEN
DLIM(1:1)=' '; DLIM(2:2)=','; DLIM(3:3)=';'; DLIM(4:4)=CHAR(9)
C
C... Group 1 Section 1
C    =================
IF(ISC==1) THEN
IF(.NOT.NULLPR) THEN
CALL WRYT40('GXBLIN of:                          200623')
CALL WRIT40('GXBLIN of:                          200623')
ENDIF
CALL GXMAKE(L0H,NXNY,'HDIS') ! storage for grid node heights
C
C... Group 1 Section 2
C    =================
ELSEIF(ISC==2) THEN
100     CONTINUE
IF(IDMN>1) CALL INDXDM ! get indices for current FGV domain
IF(NUMDMN>MAXDMN) THEN
CALL WRITBL
CALL WRITST
CALL WRIT40('Please increase MAXDMN in GXBLIN')
CALL WRIT2I('Current ',MAXDMN,'; Needed',NUMDMN)
CALL WRITST
CALL SET_ERR(557,'MAXDMN too small in GXBLIN',1)
RETURN
ENDIF
C... Count how many BLINs
NBLIN(IDMN)=0
DO IP=1,NUMPAT
IF((NAMPAT(IP)(1:4)=='BLIN'.OR.NAMPAT(IP)(1:4)=='GXBL')
1                       .AND.LPTDMN(IP)) NBLIN(IDMN)=NBLIN(IDMN)+1
ENDDO
C
IF(NBLIN(IDMN)==0) RETURN ! no BLINs so nothing to do
IF(.NOT.ALLOCATED(L0HI)) THEN
ALLOCATE(L0HI(MAXDMN,NBLIN(IDMN)),STAT=IERR)
IF(IERR==0) THEN
L0HI=0
ELSE
CALL WRITBL
CALL WRITST
CALL WRIT40('Memory allocation error in GXBLIN')
CALL WRITST
CALL SET_ERR(557,'Memory allocation error in GXBLIN',1)
RETURN
ENDIF
ENDIF
C... check for humidity and VABS
IHUM=0; IHUNIT=2; LBVABS=0
DO IPH=NPHI,16,-1
IF(NAME(IPH)=='MH2O') THEN
IHUM=IPH
CALL GETSDI('BLIN','HUNIT',IHUNIT)
ELSEIF(NAME(IPH)=='VABS') THEN
LBVABS=IPH
ENDIF
ENDDO
C... Allocate storage for BLIN parameters
CALL GXMAKE0(L0IPAT(IDMN),NUMPAT,'L0IPAT')
CALL GXMAKE(L0VELX(IDMN),NBLIN(IDMN),'L0VELX')
CALL GXMAKE(L0VELY(IDMN),NBLIN(IDMN),'L0VELY')
CALL GXMAKE(L0VELZ(IDMN),NBLIN(IDMN),'L0VELZ')
CALL GXMAKE(L0QREF(IDMN),NBLIN(IDMN),'L0QREF')
CALL GXMAKE(L0TAIR(IDMN),NBLIN(IDMN),'L0TAIR')
CALL GXMAKE(L0PCOE(IDMN),NBLIN(IDMN),'L0PCOE')
CALL GXMAKE(L0PVAL(IDMN),NBLIN(IDMN),'L0PVAL')
CALL GXMAKE(L0RELH(IDMN),NBLIN(IDMN),'L0RELH')
CALL GXMAKE(L0VDIR(IDMN),NBLIN(IDMN),'L0VDIR')
CALL GXMAKE(L0ZREF(IDMN),NBLIN(IDMN),'L0ZREF')
CALL GXMAKE(L0HREF(IDMN),NBLIN(IDMN),'L0HREF')
CALL GXMAKE(L0BLTY(IDMN),NBLIN(IDMN),'L0BLTY')
CALL GXMAKE(L0DENS(IDMN),NBLIN(IDMN),'L0DENS')
CALL GXMAKE(L0POWR(IDMN),NBLIN(IDMN),'L0POWR')
CALL GXMAKE0(L0SKY(IDMN), NBLIN(IDMN),'L0SKY')
IF(LBVABS<=0) CALL GXMAKE(L0VAB(IDMN),NX*NY,'VABS')

C... Get Weather data
EPWNAM=' ';CALL GETSDC('BLIN','WEATHERFILE',EPWNAM)
NL=0
LOCATION=' '; CALL GETSDC('BLIN','LOCATION',LOCATION) ! Location
CALL GETSDI('BLIN','NLINES',NL)
NPHOUR=1; CALL GETSDI('BLIN','NPHOUR',NPHOUR)
IF(NL>0) THEN
ALLOCATE(WSPD(NL),WDIR(NL),AIRTEMP(NL),ATMPRES(NL),
1                                             RELHUM(NL),STAT=IERR)
WSDP=0.; WDIR=0.; AIRTEMP=0.; ATMPRES=0.; RELHUM=0.
DO I=1,NL
WRITE(LINE,'(''LINE'',I4)') I
LL=8; CALL REMSPC(LINE,LL)
CALL GETSDC('BLIN',LINE(1:LL),CVAL)
LL=LENGZZ(CVAL)
CALL SPLTZZZ(CVAL,WD,NWDS,NCHARS,LL,DLIM,20)
WDIR(I)=RRDZZZ(1);WSPD(I)=RRDZZZ(2);AIRTEMP(I)=RRDZZZ(3)
CALL GETSDC('BLINA',LINE(1:LL),CVAL)
LL=LENGZZ(CVAL)
CALL SPLTZZZ(CVAL,WD,NWDS,NCHARS,LL,DLIM,20)
ATMPRES(I)=RRDZZZ(1); RELHUM(I)=RRDZZZ(2)
ENDDO
ENDIF
ENDIF
WDIRN=-999.0; CALL GETSDR('BLIN','WDIR',WDIRN)
AXDIR=0.0; CALL GETSDR('BLIN','AXDIR',AXDIR)
INIBUOY=1; CALL GETSDI('BLIN','INIBUOY',INIBUOY)
C... Now loop over BLINs, extract parameters and save
NBLIN(IDMN)=0
DO IP=1,NUMPAT
IF(.NOT.LPTDMN(IP)) GO TO 103
C... allow GENTRA particles to pass through WIND/WIND_PROFILE
IF(NAMPAT(IP)(1:4)=='BLIN'.OR.NAMPAT(IP)(1:4)=='GXBL') THEN
NBLIN(IDMN)=NBLIN(IDMN)+1
F(L0IPAT(IDMN)+IP)=NBLIN(IDMN)
CTEMP=NAMPAT(IP)
CALL GETCV(IP,1,GCO,GVAL)
IF(QEQ(GCO,-999.0)) CYCLE ! no settings for ground plane
C.. inlet velocity vector at reference height (will be overwritten for tabular input)
VELX=0.0; VELY=0.0; VELZ=0.0
CALL GETSDR(CTEMP,'VELX',VELX)
F(L0VELX(IDMN)+NBLIN(IDMN))=VELX
CALL GETSDR(CTEMP,'VELY',VELY)
F(L0VELY(IDMN)+NBLIN(IDMN))=VELY
CALL GETSDR(CTEMP,'VELZ',VELZ)
F(L0VELZ(IDMN)+NBLIN(IDMN))=VELZ
C.. compute inlet velocity magnitude at reference height
QREF = SQRT ( VELX*VELX + VELY*VELY + VELZ*VELZ )
F(L0QREF(IDMN)+NBLIN(IDMN))=QREF
C... external temperature
TAIR=20.0; CALL GETSDR(CTEMP,'TAIR',TAIR)
F(L0TAIR(IDMN)+NBLIN(IDMN))=TAIR
C... pressure coefficient & value
PCOEF=1000.0; CALL GETSDR(CTEMP,'PCOEF',PCOEF)
F(L0PCOE(IDMN)+NBLIN(IDMN))=PCOEF
PEXT=0.0;  CALL GETSDR(CTEMP,'PEXT',PEXT)
C... External pressure always 0 relative to PRESS0, which is set to atmospheric
F(L0PVAL(IDMN)+NBLIN(IDMN))=PEXT
C... humidity
IF(IHUM>0) THEN
HUMIN=0.0; CALL GETSDR(CTEMP,'HUMIN',HUMIN)
IF(IHUNIT>0) THEN
IF(IHUNIT==1) THEN ! convert from humidity ratio
HUMIN=1.E-3*HUMIN
ELSEIF(IHUNIT==2) THEN ! convert from relative humidity
TIN=TAIR+TEMP0-273.    ! convert to deg C
CALL GETSDR(CTEMP,'PEXT',PEXT)
PIN=PEXT
PVAP = 1.E-2*HUMIN*PVH2O(TIN)
C... save Relative humidity for printout
GWRAT = 18.015/28.96; RELH=HUMIN
HUMIN = GWRAT*PVAP/(PIN-PVAP)
ENDIF
HUMIN=HUMIN/(1+HUMIN) ! convert to mass fraction
ENDIF
F(L0RELH(IDMN)+NBLIN(IDMN))=HUMIN
ENDIF
C.. vertical coordinate direction
VDIR='Z'; CALL GETSDC(CTEMP,'VDIR',VDIR)
IF(VDIR=='X') THEN
F(L0VDIR(IDMN)+NBLIN(IDMN))=1.
ELSEIF(VDIR=='Y') THEN
F(L0VDIR(IDMN)+NBLIN(IDMN))=2.
ELSEIF(VDIR=='Z') THEN
F(L0VDIR(IDMN)+NBLIN(IDMN))=3.
ENDIF
C.. inlet density
RHOIN=1.189; CALL GETSDR(CTEMP,'RHOIN',RHOIN)
F(L0DENS(IDMN)+NBLIN(IDMN))=RHOIN
C.. profile type = TABLE (3) for tabular,
C                  POWL  (2) for power law &
C                  LOGL  (1) for log law
BLTY='LOGL'; CALL GETSDC(CTEMP,'BLTY',BLTY)
F(L0BLTY(IDMN)+NBLIN(IDMN))=1
IF(BLTY=='POWL') F(L0BLTY(IDMN)+NBLIN(IDMN))=2
IF(BLTY=='TABLE') F(L0BLTY(IDMN)+NBLIN(IDMN))=3
C.. effective roughness length
ZO=0.1; CALL GETSDR(CTEMP,'ZO',ZO)
F(L0ZREF(IDMN)+NBLIN(IDMN))=ZO
C.. reference height for wind reference velocity
REFH=10.0; CALL GETSDR(CTEMP,'REFH',REFH)
F(L0HREF(IDMN)+NBLIN(IDMN))=REFH
C
IF(BLTY=='POWL') THEN
ALPHA=1./7.; CALL GETSDR(CTEMP,'ALPHA',ALPHA)
F(L0POWR(IDMN)+NBLIN(IDMN))=ALPHA
ENDIF
CALL GETPAT(IP,IREG,TYP,JXF,JXL,JYF,JYL,JZF,JZL,JTF,JTL)
IPBC=0
C... Get lower limit of open area for each BLIN
IF(VDIR=='Z') THEN ! UP direction is Z. Deal with X-Z and Y-Z
IF(QEQ(TYP,1.0)) THEN  ! CELL, initialisation
I1=JXF; I2=JXL; J1=JYF; J2=JYL; K1=1; K2=NZ
NDIM=NX*NY ! need NXNY edge locations
F(L0SKY(IDMN)+NBLIN(IDMN))=-1
ELSEIF(TYP<4.) THEN ! West/East (TYP= 3 or 2)
I1=ITWO(JXF,JXL,TYP>2.) ! JXF if TYP=3, JXL if TYP=2
I2=ITWO(JXF,JXL,TYP>2.)
J1=JYF; J2=JYL; K1=JZF; K2=JZL
NDIM=NY ! need NY edge locations
ELSEIF(TYP<6.) THEN  ! South/North (TYP= 5 or 4)
I1=JXF; I2=JXL
J1=ITWO(JYF,JYL,TYP>4.) ! JYF if TYP=5, JYL if TYP=4
J2=ITWO(JYF,JYL,TYP>4.)
K1=JZF; K2=JZL
NDIM=NX ! need NX edge locations
ELSE ! High/Low (TYP = 6 or 7) for SKY
I1=JXF; I2=JXL; J1=JYF; J2=JYL; K1=1; K2=NZ
NDIM=NX*NY ! need NXNY edge locations
F(L0SKY(IDMN)+NBLIN(IDMN))=1
ENDIF
CALL GXMAKE0(L0HI(IDMN,NBLIN(IDMN)),NDIM,'L0HI')
L0DIST=L0F(ZWNZ)
ISKY=F(L0SKY(IDMN)+NBLIN(IDMN))
C... loop over area of BLIN to find first open cell
DO IX=I1,I2
DO IY=J1,J2
DIST=0.0
DO IZZ=K1,K2
IZZM1=(IZZ-1)*NXNY
L0FACZ= L0FACE+IZZM1
I=(IX-1)*NY+IY
IJKDM=I+IZZM1
IF(ISKY==0) THEN
IB=ITWO(IX,IY,TYP>3.)
ELSE
IB=I
ENDIF
IF(PARSOL) IPBC = IPBSEQ(IDMN,IJKDM) ! get cut-cell number
IF(IPBC>0.AND.ISKY==0) THEN          ! dealing with cut cel
IT1= ISHPB(IDMN,IPBC)
DIST = F(IT1+PBC_CTCEN(3)) ! cut-face centre in Z
F(L0HI(IDMN,NBLIN(IDMN))+IB)=DIST
GO TO 1001 ! next column
ELSEIF(.NOT.SLD(I)) THEN ! open cell
IF(IZZ>1.AND.(LWP(I).OR.SLD(I-NXNY)))
1                                              DIST=F(L0DIST+IZZ-1)
F(L0HI(IDMN,NBLIN(IDMN))+IB)=DIST
GO TO 1001 ! next column
ENDIF
ENDDO
1001               CONTINUE
ENDDO
ENDDO
C... if domain is split in Z and UP direction is Z, must propagate
C    terrain height to all processors at higher (Z) level
IF(MIMD.AND.NPROC>1.AND.TYP<6.) THEN ! parallel & E,W,N or S
C... Must send terrain height from lowest (in Z) processors to upper ones.
IF(NZSD>1) THEN ! domain is split in Z
ITAG=4880; IXSD=IDX+1; IYSD=IDY+1; IZSD=IDZ+1
NCELLS=ITWO(I2-I1+1, J2-J1+1,TYP>3.)
IF(IZSD0) THEN ! send to above
CALL SENDI_FOR(NCELLS,1,ITAG,IDD)
CALL SENDR_FOR(BUFF,NCELLS,ITAG,IDD)
ENDIF
ENDIF
DEALLOCATE(BUFF,STAT=IERR)
ENDIF
ENDIF
ELSEIF(VDIR=='Y') THEN ! UP direction is Y. Deal with Z-Y and X-Y
IF(QEQ(TYP,1.0)) THEN  ! CELL, initialisation
I1=JXF; I2=JXL; K1=JZF; K2=JZL; J1=1; J2=NY
NDIM=NX*NZ
F(L0SKY(IDMN)+NBLIN(IDMN))=-1
ELSEIF(TYP<4.) THEN ! West/East (TYP= 3 or 2)
I1=ITWO(JXF,JXL,TYP>2.)
I2=ITWO(JXF,JXL,TYP>2.)
J1=JYF; J2=JYL; K1=JZF; K2=JZL
NDIM=NZ
ELSEIF(TYP>5.) THEN          ! Low/High (TYP= 7 or 6)
I1=JXF; I2=JXL; J1=JYF; J2=JYL
K1=ITWO(JZF,JZL,TYP>6.) ! JZF if TYP=7, JZL if TYP=6
K2=ITWO(JZF,JZL,TYP>6.)
NDIM=NX
ELSE  ! North/south for SKY
I1=JXF; I2=JXL; K1=JZF; K2=JZL; J1=1; J2=NY
NDIM=NX*NZ
F(L0SKY(IDMN)+NBLIN(IDMN))=1
ENDIF
CALL GXMAKE0(L0HI(IDMN,NBLIN(IDMN)),NDIM,'L0HI')
L0DIST=L0F(YV2D)
ISKY=F(L0SKY(IDMN)+NBLIN(IDMN))
C... loop over area of BLIN to find first open cell
DO IX=I1,I2
DO IZZ=K1,K2
IZZM1=(IZZ-1)*NXNY
L0FACZ= L0FACE+IZZM1
DIST=0.0
DO IY=J1,J2
I=(IX-1)*NY+IY
IJKDM=I+IZZM1
IF(ISKY==0) THEN
IB=ITWO(IX,IZZ,TYP>5.)
ELSE
IB=(IX-1)*NZ+IZZ
ENDIF
IF(PARSOL) IPBC = IPBSEQ(IDMN,IJKDM) ! get cut-cell number
IF(IPBC>0.AND.ISKY==0) THEN          ! dealing with cut cel
IT1= ISHPB(IDMN,IPBC)
DIST = F(IT1+PBC_CTCEN(2)) ! cut-face centre in Y
F(L0HI(IDMN,NBLIN(IDMN))+IB)=DIST
GO TO 1002
ELSEIF(.NOT.SLD(I)) THEN ! open cell
IF(IY>1.AND.(SWP(I).OR.SLD(I-1)))
1                                                DIST=F(L0DIST+I-1)
F(L0HI(IDMN,NBLIN(IDMN))+IB)=DIST
GO TO 1002
ENDIF
ENDDO
1002               CONTINUE
ENDDO
ENDDO
C... if domain is split in Y and UP direction is Y, must propagate
C    terrain height to all processors at higher (Y) level
IF(MIMD.AND.NPROC>1.AND.(TYP<4..OR.TYP>5.)) THEN ! parallel & E,W,H or L
C... Must send terrain height from lowest (in Z) processors to upper ones.
IF(NYSD>1) THEN ! domain is split in Z
ITAG=4880; IXSD=IDX+1; IYSD=IDY+1; IZSD=IDZ+1
NCELLS=ITWO(I2-I1+1, K2-K1+1,TYP>5.)
IF(IYSD0) THEN ! send to above
CALL SENDI_FOR(NCELLS,1,ITAG,IDD)
CALL SENDR_FOR(BUFF,NCELLS,ITAG,IDD)
ENDIF
ENDIF
DEALLOCATE(BUFF,STAT=IERR)
ENDIF
ENDIF
ELSEIF(VDIR=='X') THEN ! UP direction is X. Deal with Z-X and Y-X
IF(QEQ(TYP,1.0)) THEN  ! CELL, initialisation
K1=JZF; K2=JZL; J1=JYF; J2=JYL; I1=1; I2=NX
NDIM=NZ*NY
F(L0SKY(IDMN)+NBLIN(IDMN))=-1
ELSEIF(TYP>5.) THEN ! Low/High
I1=JXF; I2=JXL; J1=JYF; J2=JYL
K1=ITWO(JZF,JZL,TYP>6.) ! JZF if TYP=7, JZL if TYP=6
K2=ITWO(JZF,JZL,TYP>6.)
NDIM=NY
ELSEIF(TYP>3.) THEN               ! South/North
I1=JXF; I2=JXL
J1=ITWO(JYF,JYL,TYP>4) ! JYF if TYP=5, JYL if TYP=4
J2=ITWO(JYF,JYL,TYP>4)
K1=JZF; K2=JZL
NDIM=NZ
ELSE          ! East/West for SKY
K1=JZF; K2=JZL; J1=JYF; J2=JYL; I1=1; I2=NX
NDIM=NZ*NY
F(L0SKY(IDMN)+NBLIN(IDMN))=1
ENDIF
CALL GXMAKE0(L0HI(IDMN,NBLIN(IDMN)),NDIM,'L0HI')
L0DIST=L0F(XU2D)
ISKY=F(L0SKY(IDMN)+NBLIN(IDMN))
C... loop over area of BLIN to find first open cell
DO IZZ=K1,K2
IZZM1=(IZZ-1)*NXNY
L0FACZ= L0FACE+IZZM1
DO IY=J1,J2
DIST=0.0
DO IX=I1,I2
I=(IX-1)*NY+IY
IJKDM=I+IZZM1
IF(ISKY==0) THEN
IB=ITWO(IY,IZZ,TYP>5.)
ELSE
IB=(IY-1)*NZ+IZZ
ENDIF
IF(PARSOL) IPBC = IPBSEQ(IDMN,IJKDM) ! get cut-cell number
IF(IPBC>0.AND.ISKY==0) THEN          ! dealing with cut cell
IT1= ISHPB(IDMN,IPBC)
DIST = F(IT1+PBC_CTCEN(1)) ! cut-face centre in X
F(L0HI(IDMN,NBLIN(IDMN))+IB)=DIST
GO TO 1003
ELSEIF(.NOT.SLD(I)) THEN ! open cell
IF(IX>1.AND.(WWP(I).OR.SLD(I-NY)))
1                                               DIST=F(L0DIST+I-NY)
F(L0HI(IDMN,NBLIN(IDMN))+IB)=DIST
GO TO 1003
ENDIF
ENDDO
1003               CONTINUE
ENDDO
ENDDO
C... if domain is split in X and UP direction is X, must propagate
C    terrain height to all processors at higher (X) level
IF(MIMD.AND.NPROC>1.AND.TYP>3.) THEN ! parallel & N, S, H or L
C... Must send terrain height from lowest (in X) processors to upper ones.
IF(NXSD>1) THEN ! domain is split in X
ITAG=4880; IXSD=IDX+1; IYSD=IDY+1; IZSD=IDZ+1
NCELLS=ITWO(J2-J1+1, K2-K1+1,TYP>5.)
IF(IXSD0) THEN ! send to above
CALL SENDI_FOR(NCELLS,1,ITAG,IDD)
CALL SENDR_FOR(BUFF,NCELLS,ITAG,IDD)
ENDIF
ENDIF
DEALLOCATE(BUFF,STAT=IERR)
ENDIF
ENDIF
ENDIF
ENDIF
103       CONTINUE
ENDDO
IF(ITEM1>0) THEN
ITPRO=0            ! Uniform temperature profile
CALL GETSDI('BLIN','ITPRO',ITPRO)
C
IF(ITPRO.GT.0) THEN
GZT0  = 0.0          ! ZT0 - surface-temperature reference height
CALL GETSDR('BLIN','GZT0',GZT0)
GT0   = TAIR          ! Temperature at ZT0
CALL GETSDR('BLIN','GT0',GT0)
GQWALL = 0.0       ! Ground heat flux
CALL GETSDR('BLIN','GQWALL',GQWALL)
GALR = 9.81/CP1      ! Dry adiabatic lapse rate
MOLEN=2              ! User-specified Monin-Obukhov length
CALL GETSDI('BLIN','MOLEN',MOLEN)
C
IF(ITPRO==1) THEN      ! Class A: Very unstable
PASQUILL='Pasquill Class A'
IF(MOLEN==1) THEN
GLS=33.162 ; GZS=1117.0  ! TNO
ELSE IF(MOLEN==2) THEN
ALMO=-11.4 ; BLMO=0.1    ! PHAST
ENDIF
ELSEIF(ITPRO==2) THEN     ! Class B: Moderately unstable
PASQUILL='Pasquill Class B'
IF(MOLEN==1) THEN
GLS=32.258 ; GZS=11.46  ! TNO
ELSE IF(MOLEN==2) THEN
ALMO=-26.0 ; BLMO=0.17    ! PHAST
ENDIF
ELSEIF(ITPRO==3) THEN ! Class C: Slightly unstable
PASQUILL='Pasquill Class C'
IF(MOLEN==1) THEN
GLS=51.787 ; GZS=1.324  ! TNO
ELSE IF(MOLEN==2) THEN
ALMO=-123.0 ; BLMO=0.3    ! PHAST
ENDIF
ELSEIF(ITPRO==4) THEN ! Class D: Neutral
PASQUILL='Pasquill Class D'
ELSEIF(ITPRO==5) THEN  ! Class E: Slightly stable
PASQUILL='Pasquill Class E'
IF(MOLEN==1) THEN
GLS=-48.33 ; GZS=1.262  ! TNO
ELSE IF(MOLEN==2) THEN
ALMO=123.0 ; BLMO=0.3    ! PHAST
ENDIF
ELSEIF(ITPRO==6) THEN  ! Class F: Moderately stable
PASQUILL='Pasquill Class F'
C.. Monin Obukhov length
IF(MOLEN==1) THEN
GLS=-31.325 ; GZS=19.36    ! TNO
ELSE IF(MOLEN==2) THEN
ALMO=26.0 ; BLMO=0.17    ! PHAST
ENDIF
ENDIF
IF(MOLEN==0) THEN
GLM0 = 1.0
CALL GETSDR('GLMO','GLMO',GLMO) ! User value
ELSE IF(MOLEN==1) THEN
ZODZS= AMAX1(ZO,0.5)/GZS
GLMO = GLS/LOG10(ZODZS)  ! TNO
ELSE IF(MOLEN==2) THEN
GLMO=ALMO*(ZO)**BLMO     ! PHAST
ENDIF
PASQBUOY=.FALSE.; BUOSSG=.FALSE.
DO IP=1,NUMPAT
IF(NAMPAT(IP)(1:8)=='BUOYANCY') THEN
PASQBUOY=.TRUE.
DO JIND=U1,W1,2
CALL GETCV(IP,JIND,GCO,GVAL)
IF(QEQ(GVAL,GRND3)) BUOSSG=.TRUE.
ENDDO
ENDIF
ENDDO
LBTREF=LBNAME('TREF')
IF(LBTREF<=0)  CALL GXMAKE0(L0TREF0,NX*NY*NZ,'TREF')
IF(.NOT.BUOSSG) THEN
LBPIN  =LBNAME('PIN')
IF(LBPIN<=0) CALL GXMAKE0(L0PIN0,NX*NY*NZ,'PIN')
LBRHIN =LBNAME('RHIN')
IF(LBRHIN<=0) CALL GXMAKE0(L0RHIN0,NX*NY*NZ,'RHIN')
ENDIF
CALL WRITST
CALL WRIT40(' Pasquill-Class data ')
CALL WRIT40(' --------------------')
WRITE(14,*) ' ITPRO = ',ITPRO
WRITE(14,*) ' ',PASQUILL
WRITE(14,*) ' Ground surface temperature  = ',GT0, ' C'
WRITE(14,*) ' Monin-Obukhov length        = ',GLMO,' m'
WRITE(14,*) ' Ground heat flux            = ',GQWALL,
1                      ' W/m^2'
WRITE(14,*) ' Dry adiabatic lapse rate    = ',GALR*1.E3,
1                      ' C/km'
IF(BUOSSG) THEN
WRITE(14,*) ' Boussinesq buoyancy'
ELSE
WRITE(14,*) ' Density-difference buoyancy'
ENDIF
CALL WRITBL
ENDIF
ENDIF
C... Wind amplification factor (1)
SHOWCOMF=.FALSE.; CALL GETSDL('FLAIR','SHOWCOMF',SHOWCOMF)
C... Wind amplification factor WAF (2)
LBWAF=LBNAME('WAF') !  WAF = Vabs/(profile speed at local height)
C... Wind Attenuation Coefficient WAT
LBWAT=LBNAME('WAT') !  WAT = (Vabs/(profile speed at local height))-1
IF((LBWAF>0.OR.LBWAT>0).AND.VDIR=='Z') THEN
CALL GXMAKE0(L0HIWAF(IDMN),NXNY,'L0HIWAF') ! store for height of surface
L0DIST=L0F(ZWNZ)
TERRNAM=' '; IBLK=0
CALL GETSDC('FLAIR','TERRAIN',TERRNAM) ! get name of parent
IF(TERRNAM.NE.' ') THEN  ! parent name set, so find patch number
LPAR=MIMD.AND.NPROC.GT.1
ILIM=ITWO(GD_NUMPAT,NUMPAT,LPAR) ! for parallel loop over global patches
DO III=1,ILIM
IF(LPAR) THEN ! get object name for parallel
COBNM2=GD_OBJNAM(III)
ELSE
COBNM2= OBJNAM(III)
ENDIF
IF(COBNM2.EQ.TERRNAM) THEN
IF(LPAR) THEN
IBLK=GD_INDPAT(III,1)
ELSE
IBLK=III
ENDIF
EXIT
ENDIF
ENDDO
ENDIF
DO IX=1,NX
DO IY=1,NY
I=(IX-1)*NY+IY
DIST=0.0
DO IZZ=1,NZ ! scan up column at IX,IY
L0FACZ=L0FACE+(IZZ-1)*NX*NY ! increment index for SLD()
!                  IF(IBLK>0) THEN ! have named terrain object
L0PAT=L0PATNO(IDMN)+(IZZ-1)*NXNY ! index for patch-number store
CALL GET_SURFACE(IX,IY,IZZ,IBLK,L0PAT,CAREA,
1                                                    NORML,IPLUS)
IF(CAREA>0.0) THEN
IZZM1=(IZZ-1)*NXNY; L0FACZ= L0FACE+IZZM1
IJKDM=I+IZZM1
IF(PARSOL) IPBC = IPBSEQ(IDMN,IJKDM) ! get cut-cell number
IF(IPBC>0) THEN        ! dealing with cut cel
IT1= ISHPB(IDMN,IPBC)
DIST = F(IT1+PBC_CTCEN(3)) ! cut-face centre in Z
GO TO 1004 ! next column
ELSEIF(.NOT.SLD(I)) THEN ! open cell
IF(IZZ>1.AND.(LWP(I).OR.SLD(I-NXNY))) THEN
DIST=F(L0DIST+IZZ-1)
ENDIF
GO TO 1004 ! next column
ENDIF
ENDIF
!                  ELSEIF(.NOT.SLD(I)) THEN ! open cell
!                    IF(IZZ>1.AND.(LWP(I).OR.SLD(I-NXNY))) THEN
!                      DIST=F(L0DIST+IZZ-1)
!                    ENDIF
!                    GO TO 1004 ! next column
!                  ENDIF
ENDDO ! end IZ loop
1004           CONTINUE
F(L0HIWAF(IDMN)+I)=DIST ! store surface height
ENDDO ! end IY loop
ENDDO   ! end IX loop
IF(MIMD.AND.NPROC>1) THEN ! parallel
C... Must send terrain height from lowest (in Z) processors to upper ones.
IF(NZSD>1) THEN ! domain is split in Z
ITAG=4880; IXSD=IDX+1; IYSD=IDY+1; IZSD=IDZ+1
NCELLS=NXNY
IF(IZSD0) THEN ! send to above
CALL SENDI_FOR(NCELLS,1,ITAG,IDD)
CALL SENDR_FOR(BUFF,NCELLS,ITAG,IDD)
ENDIF
ENDIF
DEALLOCATE(BUFF,STAT=IERR)
ENDIF ! end of split-in-Z block
ENDIF ! end of parallel block
ENDIF ! end of WAF block
C... loop back for next FGV domain
IF(IDMN1) THEN
IDMN=1
CALL INDXDM
ENDIF
C... Wind comfort
IF(SHOWCOMF) THEN
LBPRO=LBNAME('PRO')
TYPECOMF='NEN8100'; CALL GETSDC('FLAIR','TYPECOMF',TYPECOMF)
IF(TYPECOMF=='NEN8100') THEN
LBDAN=LBNAME('PDAN'); LBNEN=LBNAME('NEN')
IF(LBDAN+LBNEN<=0) CALL SET_ERR(584,
1             'Error. STORE NEN and/or PDAN missing for NEN8100',1)
UTHR=5; DTHR=15; CALL GETSDR('FLAIR','DTHR',DTHR)
ELSEIF(TYPECOMF=='LAWSON') THEN
NCRIT=5; CALL GETSDI('FLAIR','NCRIT',NCRIT)
NCRIT=MIN(NCRIT,7)
ALLOCATE(LTHRESH(NCRIT),LUTHR(NCRIT),LPRO(NCRIT,NX*NY),
1                                                        STAT=IERR)
LTHRESH=0.0; LUTHR=0.0; LPRO=0.0 ! initialise
DO IC=1,NCRIT
LTHRESH(IC)=THRESHD(IC)*100.; LUTHR(IC)=UTHRD(IC) ! take default from data statement
WRITE(LINE,'(''THRSH'',I1)') IC
CALL GETSDR('FLAIR',LINE(1:6),LTHRESH(IC))
LTHRESH(IC)=LTHRESH(IC)/100. ! convert back from %
WRITE(LINE,'(''UTHR'',I1)') IC
CALL GETSDR('FLAIR',LINE(1:5),LUTHR(IC))
WRITE(LINE,'(''PRO'',I1)') IC
LBPRB(IC)=LBNAME(LINE(1:4))
ENDDO
LBLAWS=LBNAME('LAWS')
IF(LBLAWS<=0) CALL SET_ERR(584,
1             'Error. STORE LAWS missing for Lawson',1)
ELSE
UTHR=6; CALL GETSDR('FLAIR','UTHR',UTHR)
ENDIF
WEICOEF=.FALSE.; CALL GETSDL('FLAIR','WEICOEF',WEICOEF)
LU=111
WINDFILE='NOTSET'
CALL GETSDCLONG('FLAIR','WINDFILE',WINDFILE) ! name of file
LL=LENGZZ(WINDFILE); CALL LOWCSE(WINDFILE,-LL)
IF(MIMD.AND.NPROC>1) THEN ! must copy remote file to local
CALL SEND_FILE(LU,WINDFILE,IERR)
IF(IERR.NE.0) GOTO 110
ENDIF
OPEN(LU,FILE=WINDFILE,STATUS='OLD',ERR=110)
C
DHEIGHT=-999.0 ! initialise to silly value
LBVAV=LBNAME('VAV')
IF(WEICOEF) THEN ! read Weibull parameters
LGWC=.FALSE.;CALL GETSDL('FLAIR','WEIB-GWC',LGWC)
NSECT=12; REWIND LU
READ(LU,'(A)') LINE; SITENAME=LINE   ! site name
CALL GETSDR('FLAIR','WEIB-H',DHEIGHT)
CALL GETSDR('FLAIR','WEIB-AW',AW)
CALL GETSDR('FLAIR','WEIB-AKW',AKW)
CALL GETSDR('FLAIR','WEIB-SECTP',SECTP)
ELSE ! Read probability bins
NBINS=0; NSECT=12; REWIND LU
104         CONTINUE      ! read file to count number of bins
IF(LL==0) GO TO 105 ! catch empty lines
NBINS=NBINS+1; GO TO 104
105         CONTINUE      ! 1st three lines are headers
NBINS=NBINS-3
REWIND(LU)    ! now read file properly
READ(LU,'(A)') LINE; SITENAME=LINE ! site name
READ(LU,'(A)') LINE; LL=LENGZZ(LINE) ! mast location & height
CALL SPLTZZZ(LINE,WD,NWDS,NCHARS,LL,DLIM,20)
DHEIGHT=RRDZZZ(3)
READ(LU,'(A)') LINE; LL=LENGZZ(LINE) ! no of sectors
CALL SPLTZZZ(LINE,WD,NWDS,NCHARS,LL,DLIM,20)
NSECT=IRDZZZ(1)
ALLOCATE(WNDA(NBINS+1,NSECT+1),STAT=IERR)
WNDA=0.0 ! initialise bins
CALL SPLTZZZ(LINE,WD,NWDS,NCHARS,LL,DLIM,20)
DO ISEC=1,NSECT
WNDA(1,ISEC+1)=RRDZZZ(ISEC)
ENDDO
PSUM=TINY
DO ISEC=2,NSECT+1
PSUM=PSUM+WNDA(1,ISEC)
ENDDO
DO ISEC=2,NSECT+1
WNDA(1,ISEC)=WNDA(1,ISEC)/(PSUM+TINY)
ENDDO
DO IB=2,NBINS ! read the probabilities for each bin
LL=LENGZZ(LINE)
CALL SPLTZZZ(LINE,WD,NWDS,NCHARS,LL,DLIM,20)
DO ISEC=1,NSECT+1
WNDA(IB,ISEC)=RRDZZZ(ISEC)
ENDDO
ENDDO
DO ISEC=2,NSECT+1 ! normalise probabilities for each direction
PSUM=TINY
DO IB=2,NBINS ! sum probabilities over all bins
PSUM=PSUM+WNDA(IB,ISEC)
ENDDO
DO IB=2,NBINS ! divide through by sum
WNDA(IB,ISEC)=WNDA(IB,ISEC)/PSUM
ENDDO
ENDDO
ENDIF
IF(DHEIGHT<=0.0) THEN
CALL WRITST
CALL WRIT40('ERROR! Mast (measurement) height not found')
CALL WRITST
CALL SET_ERR(583,
1                   'Error. Mast (measurement) height not found',1)
ENDIF
SECSIZE=360./NSECT ! sector size
IF(WDIRN>=360.0) THEN
WDIRN=WDIRN-360.0
ELSEIF(WDIRN<0.0) THEN
WDIRN=360.0-WDIRN
ENDIF
C... Wind speed sectors are centred on direction, so for 12 sectors of 30deg each,
C... sector 1 will be from -15 to +15
C           2               15 to  45 etc.
ISECT=MIN(NSECT,INT((WDIRN+SECSIZE/2.)/SECSIZE)+1) ! current sector
IF(LBVAV>0) THEN ! sector average velocity stored
IF(WEICOEF) THEN ! Weibull coefficients
VSECT=AW*GAMMA(1.0+1.0/AKW) ! Mean value of Weibull distribution
!!!                VSECT=AW*LOG(2.0)**(1.0/AKW) ! Median value of Weibull distribution
ELSE             ! Probability table
SECTP=WNDA(1,ISECT+1); VSECT=0.0
DO IB=2,NBINS+1
VI=0.5*(WNDA(IB,1)-WNDA(IB-1,1))+WNDA(IB-1,1)
PROB=WNDA(IB,ISECT+1)
VSECT=VSECT+VI*PROB
ENDDO
ENDIF
QREF=VSECT; REFH=DHEIGHT
ANG=WDIRN-AXDIR
IF(ANG<0.0) THEN
ANG=360.0+ANG
C... if wind angle > 360, subtract 360
ELSEIF(ANG>360) THEN
ANG=ANG-360.0
ENDIF
ANGR=ANG*ATAN(1.)/45. ! make radians
DO II=1,NBLIN(IDMN)
F(L0QREF(IDMN)+II)=QREF
F(L0HREF(IDMN)+II)=REFH
C... Update values for BLIN patches for use as inlet values in Group 13
IUP=F(L0VDIR(IDMN)+II)
IF(IUP==3) THEN     ! Up Z
VELX=-VSECT*SIN(ANGR)
VELY=-VSECT*COS(ANGR)
VELZ=0.0
ELSEIF(IUP==2) THEN ! Up Y
VELX=-VSECT*COS(ANGR)
VELY=0.0
VELZ=-VSECT*SIN(ANGR)
ELSE                  ! Up X
VELX=0.0
VELY=-VSECT*SIN(ANGR)
VELZ=-VSECT*COS(ANGR)
ENDIF
C... Set inlet velocity components
F(L0VELX(IDMN)+II)=VELX
F(L0VELY(IDMN)+II)=VELY
F(L0VELZ(IDMN)+II)=VELZ
ENDDO
ENDIF
ENDIF
C... Inlet profile tables
IF(BLTY=='TABLE') THEN
CLOSE(LU,IOSTAT=IOS); LU=111; VELFILE='NOTSET'
CALL GETSDCLONG('BLIN','U-TABLE',VELFILE) ! name of velocity file
LL=LENGZZ(VELFILE); CALL LOWCSE(VELFILE,-LL)
IF(MIMD.AND.NPROC>1) THEN ! must copy remote file to local
CALL SEND_FILE(LU,VELFILE,IERR)
IF(IERR.NE.0) THEN
WINDFILE=VELFILE; GOTO 110
ENDIF
ENDIF
OPEN(LU,FILE=VELFILE,STATUS='OLD',IOSTAT=IOS)
IF(IOS/=0) THEN
WINDFILE=VELFILE; GO TO 110
ENDIF
NLINES=0; REWIND LU
1041       CONTINUE      ! read file to count number of lines
IF(LL==0) GO TO 1051 ! catch empty lines
NLINES=NLINES+1; GO TO 1041
1051       CONTINUE      ! 1st lines is header
NLINEV=NLINES-1
ALLOCATE(VEL_TAB(NLINEV,4),STAT=IERR)
REWIND LU
ANG=WDIRN-AXDIR
IF(ANG<0.0) THEN
ANG=360.0+ANG
C... if wind angle > 360, subtract 360
ELSEIF(ANG>360) THEN
ANG=ANG-360.0
ENDIF
ANGR=ANG*ATAN(1.)/45. ! make radians
DO IL=1,NLINEV
READ(LU,'(A)') LINE; LL=LENGZZ(LINE) ! read a line
CALL SPLTZZZ(LINE,WD,NWDS,NCHARS,LL,DLIM,20)  ! split into words
IF(NWDS/=2) THEN
WRITE(LUPR1,'('' ERROR reading '',A)') VELFILE
CALL WRIT40
1          (' Velocity profile file must have 2 values per line.')
CALL WRIT40('Item 1 - Height, Item 2 - velocity')
CALL SET_ERR(583,
1          'Error. velocity profile must have 2 values per line',1)
ENDIF
VEL_TAB(IL,1)=RRDZZZ(1); VEL=RRDZZZ(2) ! get height and velocity
IF(VDIR=='Z') THEN     ! Up Z, get velocity components
VEL_TAB(IL,2)=-VEL*SIN(ANGR) ! U
VEL_TAB(IL,3)=-VEL*COS(ANGR) ! V
VEL_TAB(IL,4)= 0.0           ! W
ELSEIF(VDIR=='Y') THEN ! Up Y, get velocity components
VEL_TAB(IL,2)=-VEL*COS(ANGR) ! U
VEL_TAB(IL,3)= 0.0           ! V
VEL_TAB(IL,4)=-VEL*SIN(ANGR) ! W
ELSE                  ! Up X, get velocity components
VEL_TAB(IL,2)= 0.0           ! U
VEL_TAB(IL,3)=-VEL*SIN(ANGR) ! V
VEL_TAB(IL,4)=-VEL*COS(ANGR) ! W
ENDIF
ENDDO
QREF=SQRT(VEL_TAB(NLINEV,2)**2+VEL_TAB(NLINEV,3)**2+
1                VEL_TAB(NLINEV,4)**2)
DO II=1,NBLIN(IDMN)
F(L0VELX(IDMN)+II)=VEL_TAB(NLINEV,2) ! fill these to get flow
F(L0VELY(IDMN)+II)=VEL_TAB(NLINEV,3) ! direction at boundaries
F(L0VELZ(IDMN)+II)=VEL_TAB(NLINEV,4)
F(L0QREF(IDMN)+II)=QREF
ENDDO
CLOSE(LU,IOSTAT=IOS); LU=111; KEFILE='NOTSET'
CALL GETSDCLONG('BLIN','K-TABLE',KEFILE) ! name of KE file
LL=LENGZZ(KEFILE); CALL LOWCSE(KEFILE,-LL)
IF(MIMD.AND.NPROC>1) THEN ! must copy remote file to local
CALL SEND_FILE(LU,KEFILE,IERR)
IF(IERR.NE.0) THEN
WINDFILE=KEFILE; GOTO 110
ENDIF
ENDIF
OPEN(LU,FILE=KEFILE,STATUS='OLD',IOSTAT=IOS)
IF(IOS/=0) THEN
WINDFILE=KEFILE; GO TO 110
ENDIF
NLINES=0; REWIND LU
1042       CONTINUE      ! read file to count number of lines
IF(LL==0) GO TO 1052 ! catch empty lines
NLINES=NLINES+1; GO TO 1042
1052       CONTINUE      ! 1st lines is header
NLINEK=NLINES-1
ALLOCATE(KE_TAB(NLINEK,2),STAT=IERR)
REWIND LU
DO IL=1,NLINEK
CALL SPLTZZZ(LINE,WD,NWDS,NCHARS,LL,DLIM,20)  ! split into words
IF(NWDS/=2) THEN
WRITE(LUPR1,'('' ERROR reading '',A)') KEFILE
CALL WRIT40
1           (' K profile file must have 2 values per line.')
CALL WRIT40('Item 1 - Height, Item 2 - KE')
CALL SET_ERR(583,
1           'Error. K profile must have 2 values per line',1)
ENDIF
KE_TAB(IL,1)=RRDZZZ(1); KE_TAB(IL,2)=RRDZZZ(2) ! save height & KE
ENDDO
CLOSE(LU,IOSTAT=IOS)
ENDIF
C
CALL WRITST
CALL WRIT40(' Wind profile data')
CALL WRIT40(' -----------------')
WRITE(LUPR1,'(''  Up direction '',A1)') VDIR
CH1=CHGR_13(REFH); LT=LENGZZ(CH1)
IF(BLTY/='TABLE')
1     WRITE(LUPR1,'(''  Reference height:    '',A,'' m'')')
1                                                        CH1(1:LT)
CH1=CHGR_13(ZO); LT=LENGZZ(CH1)
WRITE(LUPR1,'(''  Roughness height:    '',A,'' m'')')
1                                                        CH1(1:LT)
IF(NEZ(WALLB)) THEN
CH1=CHGR_13(WALLB); LT=LENGZZ(CH1)
WRITE(LUPR1,'(''  Displacement height: '',A,'' m'')')
1                                                        CH1(1:LT)
ENDIF
IF(BLTY=='POWL') THEN
WRITE(LUPR1,'(''  Profile type - Power Law'')')
CH1=CHGR_13(ALPHA)
WRITE(LUPR1,'(''  Power law constant: '',A)') CH1
ELSEIF(BLTY=='LOGL') THEN
WRITE(LUPR1,'(''  Profile type - Logarithmic Law'')')
ELSE
WRITE(LUPR1,'(''  Profile type - from tables'')')
LL=LENGZZ(VELFILE)
WRITE(LUPR1,'(''  Velocity file used: '',A)') VELFILE(1:LL)
LL=LENGZZ(KEFILE)
WRITE(LUPR1,'(''  KE file used:       '',A)') KEFILE(1:LL)
ENDIF
CH1=CHGR_13(PCOEF)
WRITE(LUPR1,'(''  Pressure coeff at outflow boundaries: '',
1              A)') CH1
IF(EPWNAM/=' ') THEN ! Weather file specified
LL=LENGZZ(EPWNAM)
WRITE(LUPR1,'(''  Using weather data file '',A)')
1                                                      EPWNAM(1:LL)
IF(NL==0) THEN
CH1=CHGR_13(WDIRN); LT=LENGZZ(CH1)
WRITE(LUPR1,
1         '(''  Wind direction:      '',A,A)') CH1(1:LT),CHAR(176)
CH1=CHGR_13(QREF); LT=LENGZZ(CH1)
IF(BLTY/='TABLE') WRITE(LUPR1,
1         '(''  Wind speed:          '',A,'' m/s'')')   CH1(1:LT)
IF(ITEM1>0) THEN
CH1=CHGR_13(TAIR); LT=LENGZZ(CH1)
WRITE(LUPR1,
1         '(''  Air temperature:     '',A,A1,''C'')')   CH1(1:LT),
1                                                         CHAR(176)
ENDIF
CH1=CHGR_13(PEXT); LT=LENGZZ(CH1)
WRITE(LUPR1,
1         '(''  External pressure:   '',A,'' Pa'')')    CH1(1:LT)
IF(IHUM>0) THEN
CH1=CHGR_13(RELH); LT=LENGZZ(CH1)
WRITE(LUPR1,
1         '(''  Relative humidity:   '',A,'' %'')')     CH1(1:LT)
ENDIF
CH1=CHGR_13(RHOIN); LT=LENGZZ(CH1)
WRITE(LUPR1,
1         '(''  Air density:         '',A,'' kg/m^3'')') CH1(1:LT)
ELSE
WRITE(LUPR1,
1   '(''  Time  Direction     Speed        Temperature'',
1                       ''    Pressure      Humidity'')')
DO I=1,NL
WRITE(LUPR1,
1     '(I4,'' '',1PE13.6,'' '',1PE13.6,'' '',1PE13.6,'' '',1PE13.6,
1     '' '',1PE13.6)') I-1, WDIR(I),WSPD(I),AIRTEMP(I),ATMPRES(I),
1                      RELHUM(I)
ENDDO
ENDIF
ELSEIF(STEADY) THEN ! manual wind settings
IF(QNE(WDIRN,-999.0)) THEN
CH1=CHGR_13(WDIRN); LT=LENGZZ(CH1)
WRITE(LUPR1,
1         '(''  Wind direction:      '',A,A)') CH1(1:LT),CHAR(176)
ENDIF
CH1=CHGR_13(QREF); LT=LENGZZ(CH1)
IF(BLTY/='TABLE') THEN
WRITE(LUPR1,
1         '(''  Wind speed:          '',A,'' m/s'')')    CH1(1:LT)
ELSE
CH2=CHGR_13(VEL_TAB(NLINEV,1)); L2=LENGZZ(CH2)
WRITE(LUPR1,
1     '(''  Wind speed:          '',A,
1       '' m/s (at top of table '',A,'' m)'')') CH1(1:LT),CH2(1:L2)
ENDIF
IF(ITEM1>0) THEN
CH1=CHGR_13(TAIR); LT=LENGZZ(CH1)
WRITE(LUPR1,
1         '(''  Air temperature:     '',A,A1,''C'')')    CH1(1:LT),
1                                                         CHAR(176)
ENDIF
CH1=CHGR_13(PEXT); LT=LENGZZ(CH1)
WRITE(LUPR1,
1         '(''  External pressure:   '',A,'' Pa'')')     CH1(1:LT)
IF(IHUM>0) THEN
IF(IHUNIT==0) THEN
CH1=CHGR_13(HUMIN); LT=LENGZZ(CH1)
WRITE(LUPR1,
1         '(''  H2O mass fraction:   '',A,'' '')')       CH1(1:LT)
ELSEIF(IHUNIT==1) THEN
CH1=CHGR_13(HUMIN*1000.); LT=LENGZZ(CH1)
WRITE(LUPR1,
1         '(''  Humidity ratio:      '',A,'' g/kg'')')   CH1(1:LT)
ELSE
CH1=CHGR_13(RELH); LT=LENGZZ(CH1)
WRITE(LUPR1,
1         '(''  Relative humidity:   '',A,'' %'')')      CH1(1:LT)
ENDIF
ENDIF
CH1=CHGR_13(RHOIN); LT=LENGZZ(CH1)
WRITE(LUPR1,
1         '(''  Air density:         '',A,'' kg/m^3'')') CH1(1:LT)
ENDIF
C... Pressure coefficient
LBCP=LBNAME('CP')
IF(SHOWCOMF) THEN
CALL WRITBL
WRITE(14,'(''  Wind comfort input data'')')
WRITE(14,'(''  -----------------------'')')
LL=LENGZZ(SITENAME)
WRITE(14,'(''  Site name:  '',A)') SITENAME(1:LL)
WRITE(14,'(''  Using data for sector: '',I2)') ISECT
CH1=CHGR_13(DHEIGHT); L1=LENGZZ(CH1)
WRITE(14,'(''  Mast height:'',A)') CH1(1:L1)
IF(LBVAV>0) THEN
WRITE(14,'(''  ## Multi-sector run ##'')')
CH1=CHGR_13(SECTP); L1=LENGZZ(CH1)
CH2=CHGR_13(VSECT); L2=LENGZZ(CH2)
WRITE(LUPR1,'(''  Probability of wind in sector'',I3,
1         '' is: '',A)') ISECT,CH1(1:L1)
WRITE(LUPR1,
1        '(''  Measured average wind speed at mast height is: '',A,
1                                             '' m/s'')') CH2(1:L2)
WRITE(14,'(''  ## Wind speed was set to '',
1     ''average velocity at mast height: '',A,'' m/s'')') CH2(1:L2)
CH1=CHGR_13(DHEIGHT); L1=LENGZZ(CH1)
WRITE(14,'(''  ## Reference height was set to ''
1                           ''mast height: '',A,'' m'')') CH1(1:L1)
ENDIF
IF(BLTY=='POWL') THEN      ! power-law profile
WMAST=QREF*(DHEIGHT/REFH)**ALPHA
ELSEIF(BLTY=='LOGL') THEN   ! log profile
IF(EQZ(WALLB)) THEN
GHDZO=AMAX1(DHEIGHT/ZO,2.0)
ELSE
IF(LTZ(WALLB)) THEN
GHDZO=(DHEIGHT-WALLB)/ZO
ELSE
GHDZO=AMAX1((DHEIGHT-WALLB)/ZO,2.0)
ENDIF
ENDIF
WMAST=QREF*LOG(GHDZO)/LOG(REFH/ZO)
ELSE                       ! tabular profile
FACT=-999. ! initialize
GH=DHEIGHT ! height from probability table file
DO IL=1,NLINEV-1 ! loop over table
IF(GH>=VEL_TAB(IL,1).AND.GH<=VEL_TAB(IL+1,1)) THEN
FACT=(GH             -VEL_TAB(IL,1))/
1                 (VEL_TAB(IL+1,1)-VEL_TAB(IL,1))
ILP1=IL+1; EXIT
ENDIF
ENDDO
IF(QEQ(FACT,-999.)) THEN ! no value was found
IF(GH>=VEL_TAB(NLINEV,1)) THEN ! above top of table
IL=NLINEV ! use top value
ELSE                           ! below bottom
IL=1      ! use bottom value
ENDIF
FACT=0.0; ILP1=IL
ENDIF
UCOMP=VEL_TAB(IL,2)+FACT*(VEL_TAB(ILP1,2)-VEL_TAB(IL,2))
VCOMP=VEL_TAB(IL,3)+FACT*(VEL_TAB(ILP1,3)-VEL_TAB(IL,3))
WCOMP=VEL_TAB(IL,4)+FACT*(VEL_TAB(ILP1,4)-VEL_TAB(IL,4))
WMAST=SQRT(UCOMP*UCOMP+VCOMP*VCOMP+WCOMP*WCOMP)
ENDIF
CH2=CHGR_13(WMAST); L2=LENGZZ(CH2)
WRITE(LUPR1,
1         '(''  Wind-profile speed at mast height: '',A,'' m/s'')')
1                                                        CH2(1:L2)
IF(TYPECOMF=='NEN8100') THEN
LINE='Dutch standard NEN8100'
ELSEIF(TYPECOMF=='LAWSON') THEN
LINE='Lawson Comfort Criteria '
ELSE
CH1=CHGR_13(UTHR); LL=LENGZZ(CH1)
LINE='probability of exceeding '//CH1(1:LL)//' m/s'
ENDIF
LL=LENGZZ(LINE)
WRITE(LUPR1,'(''  Comfort type: '',A)') LINE(1:LL)
IF(TYPECOMF=='LAWSON') THEN
WRITE(LUPR1,
1      '(''   Level Probability (%) Max Speed (m/s)'')')
DO IC=1,NCRIT
CH1=CHGR_13(LTHRESH(IC)*100.)
CH2=CHGR_13(LUTHR(IC))
WRITE(LUPR1,'(5X,I1,7X,A,1X,A)') IC,CH1(1:13),CH2(1:13)
ENDDO
ENDIF
ENDIF ! end of SHOWCOMF section
C... Wind amplification factor (1)
LBWAMP=LBNAME('WAMP'); !LBVABS=LBNAME('VABS')
IF(LBWAMP>0) THEN ! WAMP is stored
WAMPH=1.5; CALL GETSDR('BLIN','WAMPH',WAMPH) ! get ref height
IF(BLTY=='POWL') THEN       ! power-law profile
WAMPVR=QREF*(WAMPH/REFH)**ALPHA
ELSEIF(BLTY=='LOGL') THEN    ! log profile
IF(EQZ(WALLB)) THEN
GHDZO=AMAX1(WAMPH/ZO,2.0)
ELSE
IF(LTZ(WALLB)) THEN
GHDZO=(WAMPH-WALLB)/ZO
ELSE
GHDZO=AMAX1((WAMPH-WALLB)/ZO,2.0)
ENDIF
ENDIF
WAMPVR=QREF*LOG(GHDZO)/LOG(REFH/ZO)
ELSE                       ! tabular profile
FACT=-999. ! initialize
GH=WAMPH
DO IL=1,NLINEV-1 ! loop over table
IF(GH>=VEL_TAB(IL,1).AND.GH<=VEL_TAB(IL+1,1)) THEN
FACT=(GH             -VEL_TAB(IL,1))/
1                 (VEL_TAB(IL+1,1)-VEL_TAB(IL,1))
ILP1=IL+1; EXIT
ENDIF
ENDDO
IF(QEQ(FACT,-999.)) THEN ! no value was found
IF(GH>=VEL_TAB(NLINEV,1)) THEN ! above top of table
IL=NLINEV ! use top value
ELSE                           ! below bottom
IL=1      ! use bottom value
ENDIF
FACT=0.0; ILP1=IL
ENDIF
UCOMP=VEL_TAB(IL,2)+FACT*(VEL_TAB(ILP1,2)-VEL_TAB(IL,2))
VCOMP=VEL_TAB(IL,3)+FACT*(VEL_TAB(ILP1,3)-VEL_TAB(IL,3))
WCOMP=VEL_TAB(IL,4)+FACT*(VEL_TAB(ILP1,4)-VEL_TAB(IL,4))
WAMPVR=SQRT(UCOMP*UCOMP+VCOMP*VCOMP+WCOMP*WCOMP)
ENDIF
CH1=CHGR_13(WAMPH); CH2=CHGR_13(WAMPVR)
WRITE(LUPR1,
1   '(''  Wind speed at '',A,''m:  '',A,'' m/s (used for WAMP)'')')
1                             CH1(1:LENGZZ(CH1)),CH2(1:LENGZZ(CH2))
ENDIF
CALL WRITST
RETURN
110     CONTINUE
LL=LENGZZ(WINDFILE)
CALL WRIT40('Cannot open wind data file '//WINDFILE(1:LL))
CALL SET_ERR(583,'Error. Cannot open wind data file',1)
C
C... Group 1 Section 3
C    =================
ELSEIF(ISC==3) THEN
ENDIF
ENDIF
C*****************************************************************
C--- GROUP 13. Boundary conditions and special sources
C                                       Index for Coefficient - CO
C                                       Index for Value       - VAL
IF(IGR==13.AND.ISC==8) THEN
C------------------- SECTION 8 ------------------- coef = GRND7
C... Set diffusive coefficient at SKY
C      CO = density*turbulent viscosity/distance
!!!C         = density*(Q*)*K*z/dz
C
C    The followed yet to be coded.
C     IF(ITPRO > 0 .AND. ITPRO /= 4) THEN
C       GPHIM = 1.0-PSIFT(GZMDH,GLMO)
C       ENUT=ENUT/GPHIM
C     ENDIF
C
IBLIN=NINT(F(L0IPAT(IDMN)+IPAT))
!!!C.. inlet velocity magnitude at reference height
!!!        QREF=F(L0QREF(IDMN)+IBLIN)
!!!C.. reference height for wind reference velocity
!!!        REFH=F(L0HREF(IDMN)+IBLIN)
!!!C.. effective roughness length
!!!        ZO=F(L0ZREF(IDMN)+IBLIN)
C.. vertical coordinate direction
IVDIR=NINT(F(L0VDIR(IDMN)+IBLIN))
C... store vertical height of grid nodes in L0H
IF(IVDIR==1) THEN     ! Up X
!!!          CALL FN0(-L0H,XU2D)
GDH=0.5*F(L0F(DXU2D)+NX)
ELSEIF(IVDIR==2) THEN ! Up Y
!!!          CALL FN0(-L0H,YV2D)
GDH=0.5*F(L0F(DYV2D)+NY)
ELSE                    ! Up Z
!!!          GH=F(L0F(ZWNZ)+IZ)
GDH=0.5*F(L0F(DZWNZ)+NZ)
!!!          CALL FN1(-L0H,GH)
ENDIF
L0CO=L0F(CO)
L0DEN=L0F(DEN1); L0VIST=L0F(VIST)
!!!C#### JCL/MRM 19.08.14 allow for 'd' constant in log profile
!!!        QTAU   = AK*QREF/(LOG((REFH-WALLB)/ZO)) ! friction velocity
IF((INDVAR.EQ.KE.OR.INDVAR.EQ.LBOMEG).AND.
1              (IENUTA.GE.17.AND.IENUTA.LE.20)) THEN
L0VIST=L0F(VIST); L0BF1 =L0F(LBBF1)
IF(INDVAR.EQ.KE) THEN
GSIG1=SIGK1 ; GSIG2=SIGK2
ELSE ! w
GSIG1=SIGW1 ; GSIG2=SIGW2
ENDIF
DO IX=IXF,IXL
DO IY=IYF,IYL
GBF1   = F(L0BF1+I)
GPRTRB = (GBF1*GSIG1 + (1.-GBF1)*GSIG2)
F(L0CO+I)=F(L0DEN+I)*F(L0VIST+I)/(GPRTRB*GDH)
ENDDO
ENDDO
ELSE
DO IX=IXF,IXL
DO IY=IYF,IYL
F(L0CO+I)=F(L0DEN+I)*F(L0VIST+I)/(PRT(INDVAR)*GDH)
ENDDO
ENDDO
ENDIF
ELSEIF(IGR==13.AND.ISC==9) THEN
C------------------- SECTION 8 ------------------- coef = GRND8
C... Set COefficient for mass-flow boundaries.
C      Set to FIXFLU if inflow, set to PCOEF if outflow.
IF(INDVAR==P1) THEN
IBLIN=NINT(F(L0IPAT(IDMN)+IPAT))
VELX=F(L0VELX(IDMN)+IBLIN)
VELY=F(L0VELY(IDMN)+IBLIN)
VELZ=F(L0VELZ(IDMN)+IBLIN)
C         check cell face to check inflow/outflow
C e=2, w=3, n=4, s=5, h=6, l=7
IF(INTTYP==2.OR.INTTYP==3) THEN     ! E or W
VELIN=VELX
ELSEIF(INTTYP==4.OR.INTTYP==5) THEN ! N or S
VELIN=VELY
ELSEIF(INTTYP==6.OR.INTTYP==7) THEN ! H or L
VELIN=VELZ
ENDIF
IF(ABS(VELIN)<=1.0E-6) VELIN=0.0
IF(INTTYP==2.OR.INTTYP==4.OR.INTTYP==6) THEN
IFLO=ITWO(0,1,VELIN<0.0)
ELSE
IFLO=ITWO(0,1,VELIN>0.0)
ENDIF
IF(IFLO==0) THEN ! inflow at this face
CALL FN1(CO,FIXFLU)
ELSE               ! outflow, treat as fixed pressure
CALL FN1(CO,F(L0PCOE(IDMN)+IBLIN))
ENDIF
ENDIF
ELSEIF(IGR==13.AND.ISC==19) THEN
C------------------- SECTION 19 ------------------- value = GRND7
C     power-law form:  Uz=Uh*(z/h)**a
C     log-law   form:  Uz=Uh*log(z/zo)/log(h/zo)
c
C.. inlet velocity vector at reference height
IBLIN=NINT(F(L0IPAT(IDMN)+IPAT))
VELX=F(L0VELX(IDMN)+IBLIN)
VELY=F(L0VELY(IDMN)+IBLIN)
VELZ=F(L0VELZ(IDMN)+IBLIN)
C.. inlet velocity magnitude at reference height
QREF=F(L0QREF(IDMN)+IBLIN)
C.. inlet temperature
TAIR=F(L0TAIR(IDMN)+IBLIN)
C.. inlet humidity
HUMIN=F(L0RELH(IDMN)+IBLIN)
C.. vertical coordinate direction
IVDIR=NINT(F(L0VDIR(IDMN)+IBLIN))
C.. inlet density
RHOIN=F(L0DENS(IDMN)+IBLIN)
C.. profile type = TABLE (3) for table, POWL (2) for power law & = LOGL (1) for log law
IBLTY=NINT(F(L0BLTY(IDMN)+IBLIN))
C.. effective roughness length
ZO=F(L0ZREF(IDMN)+IBLIN)
C.. reference height for wind reference velocity
REFH=F(L0HREF(IDMN)+IBLIN)
C
IF(IBLTY==2) ALPHA=F(L0POWR(IDMN)+IBLIN)
C
ISKY=NINT(F(L0SKY(IDMN)+IBLIN))
C... store vertical height of grid nodes in L0H
IF(IVDIR==1) THEN     ! up X
IF(ISKY==1) THEN
CALL FN0(-L0H,XU2D)
ELSE
CALL FN0(-L0H,XG2D)
ENDIF
ELSEIF(IVDIR==2) THEN ! up Y
IF(ISKY==1) THEN
CALL FN0(-L0H,YV2D)
ELSE
CALL FN0(-L0H,YG2D)
ENDIF
ELSEIF(IVDIR==3) THEN ! up Z
IF(ISKY==1) THEN
GH=F(L0F(ZWNZ)+IZ)
ELSE
GH=F(L0F(ZGNZ)+IZ)
ENDIF
CALL FN1(-L0H,GH)
ENDIF
C
C... Inlet mass flux or pressure boundary
C    ====================================
IF(INDVAR==P1) THEN
C         check cell face to calculate flux
C e=2, w=3, n=4, s=5, h=6, l=7
IF(INTTYP==2.OR.INTTYP==3) THEN     ! E or W
VELIN=VELX
ELSEIF(INTTYP==4.OR.INTTYP==5) THEN ! N or S
VELIN=VELY
ELSEIF(INTTYP==6.OR.INTTYP==7) THEN ! H or L
VELIN=VELZ
ENDIF
IF(ABS(VELIN)<=1.0E-6) VELIN=0.0
IF(INTTYP==2.OR.INTTYP==4.OR.INTTYP==6) THEN
IFLO=ITWO(0,1,VELIN<0.0)
ELSE
IFLO=ITWO(0,1,VELIN>0.0)
ENDIF
IF(IFLO==1) THEN ! fixed pressure boundary
CALL FN1(VAL,0.0)
RETURN
ENDIF
CALL GETCV(IPAT,INDVAR,GCO,GVAL)
IF(QEQ(GCO,GRND8)) THEN
AMULT=1./FIXFLU
ELSE
AMULT=1.
ENDIF
C... Set sign of mass-flux
IF(INTTYP==2.OR.INTTYP==4.OR.INTTYP==6) THEN ! E, N or H
IF(VELIN>0) THEN ! +ve vel points out, so mass is -ve
VELIN=-VELIN
ELSE                ! -ve vel points in, so mass is +ve
VELIN=ABS(VELIN)
ENDIF
ENDIF
C... Inlet mass flux
L0VAL=L0F(VAL); IPBC=0
IF(IBLTY==3) THEN ! Table profile
IF(INTTYP==2.OR.INTTYP==3) THEN     ! E or W
IVELIN=2 ! U component
ELSEIF(INTTYP==4.OR.INTTYP==5) THEN ! N or S
IVELIN=3 ! V component
ELSEIF(INTTYP==6.OR.INTTYP==7) THEN ! H or L
IVELIN=4 ! W component
ENDIF
DO IX=IXF,IXL
DO IY=IYF,IYL
IF(.NOT.SLD(I)) THEN
IJKDM=I+(IZ-1)*NX*NY
IF(PARSOL) IPBC = IPBSEQ(IDMN,IJKDM) ! get cut-cell number
IF(IPBC>0.AND.ISKY==0) THEN    ! dealing with cut cell
IT1= ISHPB(IDMN,IPBC)
GH=F(IT1+PBC_SNYDIST)   ! dist from sunny sub-cell cen.
! to cut-plane
ELSE
IF(IVDIR==1) THEN     ! up X
IF(ISKY==0) THEN
IB=ITWO(IZ,IY,ITYPE==4.OR.ITYPE==5)
ELSE
IB=(IY-1)*NZ+IZ
ENDIF
ELSEIF(IVDIR==2) THEN ! up Y
IF(ISKY==0) THEN
IB=ITWO(IZ,IX,ITYPE==2.OR.ITYPE==3)
ELSE
IB=(IX-1)*NZ+IZ
ENDIF
ELSE                    ! up Z
IF(ISKY==0) THEN
IB=ITWO(IY,IX,ITYPE==2.OR.ITYPE==3)
ELSE
IB=I
ENDIF
ENDIF
GH=AMAX1(F(L0H+I)-F(L0HI(IDMN,IBLIN)+IB),0.0)
ENDIF
VELIN=-999. ! initialize
DO IL=1,NLINEV-1 ! loop over table
IF(GH>=VEL_TAB(IL,1).AND.GH<=VEL_TAB(IL+1,1)) THEN ! linear
VELIN=VEL_TAB(IL,IVELIN)+(GH-VEL_TAB(IL,1))      ! interpolation
1                 *(VEL_TAB(IL+1,IVELIN)-VEL_TAB(IL,IVELIN))/
1                  (VEL_TAB(IL+1,1)-VEL_TAB(IL,1))
EXIT
ENDIF
ENDDO
IF(QEQ(VELIN,-999.)) THEN ! no value was found
IF(GH>=VEL_TAB(NLINEV,1)) THEN ! above top of table
VELIN=VEL_TAB(NLINEV,IVELIN) ! use top value
ELSE                           ! below bottom
VELIN=VEL_TAB(1,IVELIN)      ! use bottom value
ENDIF
ENDIF
C... Set sign of mass-flux
IF(INTTYP==2.OR.INTTYP==4.OR.INTTYP==6) THEN ! E, N or H
IF(VELIN>0) THEN ! +ve vel points out, so mass is -ve
VELIN=-VELIN
ELSE             ! -ve vel points in, so mass is +ve
VELIN=ABS(VELIN)
ENDIF
ENDIF
F(L0VAL+I)=RHOIN*VELIN*AMULT
ELSE
F(L0VAL+I)=0.0
ENDIF
ENDDO
ENDDO
ELSEIF(IBLTY==2) THEN ! Power-Law profile
VELCON=RHOIN*VELIN/REFH**ALPHA
DO IX=IXF,IXL
DO IY=IYF,IYL
IF(.NOT.SLD(I)) THEN
IJKDM=I+(IZ-1)*NX*NY
IF(PARSOL) IPBC = IPBSEQ(IDMN,IJKDM) ! get cut-cell number
IF(IPBC>0) THEN        ! dealing with cut cell
IT1= ISHPB(IDMN,IPBC)
GH=F(IT1+PBC_SNYDIST)   ! dist from sunny sub-cell cen.
! to cut-plane
ELSE
IF(IVDIR==1) THEN     ! up X
IF(ISKY==0) THEN
IB=ITWO(IZ,IY,ITYPE==4.OR.ITYPE==5)
ELSE
IB=(IY-1)*NZ+IZ
ENDIF
ELSEIF(IVDIR==2) THEN ! up Y
IF(ISKY==0) THEN
IB=ITWO(IZ,IX,ITYPE==2.OR.ITYPE==3)
ELSE
IB=(IX-1)*NZ+IZ
ENDIF
ELSE                    ! up Z
IF(ISKY==0) THEN
IB=ITWO(IY,IX,ITYPE==2.OR.ITYPE==3)
ELSE
IB=I
ENDIF
ENDIF
GH=AMAX1(F(L0H+I)-F(L0HI(IDMN,IBLIN)+IB),0.0)
ENDIF
C... divide by FIXFLU if CO was GRND8
F(L0VAL+I)=VELCON*(GH**ALPHA)*AMULT
ELSE
F(L0VAL+I)=0.0
ENDIF
ENDDO
ENDDO
ELSEIF(IBLTY==1) THEN
C... log-law profile
C    ---------------
C.. VELCON = RHOIN*(QTAU/KAPPA)
IF(ITPRO > 0 .AND. ITPRO /= 4) THEN
VELCON=RHOIN*VELIN/(LOG(REFH/ZO)-PSIF(REFH,GLMO))
ELSE              ! Neutral
VELCON=RHOIN*VELIN/LOG(REFH/ZO)
ENDIF
DO IX=IXF,IXL
DO IY=IYF,IYL
IF(.NOT.SLD(I)) THEN
IJKDM=I+(IZ-1)*NX*NY
IF(PARSOL) IPBC = IPBSEQ(IDMN,IJKDM) ! get cut-cell number
IF(IPBC>0) THEN        ! dealing with cut cell
IT1= ISHPB(IDMN,IPBC)
GH=F(IT1+PBC_SNYDIST)   ! dist from sunny sub-cell cen.
! to cut-plane
ELSE
IF(IVDIR==1) THEN     ! up X
IF(ISKY==0) THEN
IB=ITWO(IZ,IY,ITYPE==4.OR.ITYPE==5)
ELSE
IB=(IY-1)*NZ+IZ
ENDIF
ELSEIF(IVDIR==2) THEN ! up Y
IF(ISKY==0) THEN
IB=ITWO(IZ,IX,ITYPE==2.OR.ITYPE==3)
ELSE
IB=(IX-1)*NZ+IZ
ENDIF
ELSE                    ! up Z
IF(ISKY==0) THEN
IB=ITWO(IY,IX,ITYPE==2.OR.ITYPE==3)
ELSE
IB=I
ENDIF
ENDIF
GH=AMAX1(F(L0H+I)-F(L0HI(IDMN,IBLIN)+IB),0.0)
ENDIF
IF(EQZ(WALLB)) THEN
GHDZO=AMAX1(GH/ZO,2.0)
ELSE
IF(LTZ(WALLB)) THEN
GHDZO=(GH-WALLB)/ZO
ELSE
GHDZO=AMAX1((GH-WALLB)/ZO,2.0)
ENDIF
ENDIF
C... divide by FIXFLU if CO was GRND8
C.. VELCON = RHOIN*(QTAU/KAPPA)
IF(ITPRO > 0 .AND. ITPRO /= 4) THEN
F(L0VAL+I)=VELCON*(LOG(GHDZO)-PSIF(GH,GLMO))*AMULT
ELSE              ! Neutral
F(L0VAL+I)=VELCON*LOG(GHDZO)*AMULT
ENDIF
ELSE
F(L0VAL+I)=0.
ENDIF
ENDDO
ENDDO
ENDIF
C
C... Inlet velocity components
C    =========================
ELSEIF(INDVAR==U1.OR.INDVAR==V1.OR.INDVAR==W1) THEN
L0VAL=L0F(VAL); l0velin=0
IF(INDVAR==U1) THEN
VELIN=VELX
lbvelin=lbname('UIN')
ELSEIF(INDVAR==V1) THEN
VELIN=VELY
lbvelin=lbname('VIN')
ELSEIF(INDVAR==W1) THEN
VELIN=VELZ
lbvelin=lbname('WIN')
ENDIF
if(lbvelin>0) l0velin=l0f(lbvelin)
C
IPBC=0
IF(IBLTY==3) THEN ! Table profile
IVELIN=(INDVAR-1)/2+1 ! get component in table, column 2,3 or 4
DO IX=IXF,IXL
DO IY=IYF,IYL
IF(.NOT.SLD(I)) THEN
IJKDM=I+(IZ-1)*NX*NY
IF(PARSOL) IPBC = IPBSEQ(IDMN,IJKDM) ! get cut-cell number
IF(IPBC>0.AND.ISKY==0) THEN          ! dealing with cut cell
IT1= ISHPB(IDMN,IPBC)
GH=F(IT1+PBC_SNYDIST)   ! dist from sunny sub-cell cen.
! to cut-plane
ELSE
IF(IVDIR==1) THEN     ! up X
IF(ISKY==0) THEN
IB=ITWO(IZ,IY,ITYPE==4.OR.ITYPE==5)
ELSE
IB=(IY-1)*NZ+IZ
ENDIF
ELSEIF(IVDIR==2) THEN ! up Y
IF(ISKY==0) THEN
IB=ITWO(IZ,IX,ITYPE==2.OR.ITYPE==3)
ELSE
IB=(IX-1)*NZ+IZ
ENDIF
ELSE                    ! up Z
IF(ISKY==0) THEN
IB=ITWO(IY,IX,ITYPE==2.OR.ITYPE==3)
ELSE
IB=I
ENDIF
ENDIF
GH=AMAX1(F(L0H+I)-F(L0HI(IDMN,IBLIN)+IB),0.0)
ENDIF
VELIN=-999. ! initalise
DO IL=1,NLINEV-1 ! loop over table
IF(GH>=VEL_TAB(IL,1).AND.GH<=VEL_TAB(IL+1,1)) THEN ! linear
VELIN=VEL_TAB(IL,IVELIN)+(GH-VEL_TAB(IL,1))      ! interpolation
1                 *(VEL_TAB(IL+1,IVELIN)-VEL_TAB(IL,IVELIN))/
1                  (VEL_TAB(IL+1,1)-VEL_TAB(IL,1))
EXIT
ENDIF
ENDDO
IF(QEQ(VELIN,-999.)) THEN ! no value found
IF(GH>=VEL_TAB(NLINEV,1)) THEN ! above top of table
VELIN=VEL_TAB(NLINEV,IVELIN) ! use top value
ELSE                           ! below bottom of table
VELIN=VEL_TAB(1,IVELIN)      ! use bottom value
ENDIF
ENDIF
F(L0VAL+I)=VELIN
ELSE
F(L0VAL+I)=0.0
ENDIF
if(l0velin>0) f(l0velin+i)=f(l0val+i)
ENDDO
ENDDO
ELSEIF(IBLTY==2) THEN ! Power-Law profile
VELCON=VELIN/REFH**ALPHA
DO IX=IXF,IXL
DO IY=IYF,IYL
IF(.NOT.SLD(I)) THEN
IJKDM=I+(IZ-1)*NX*NY
IF(PARSOL) IPBC = IPBSEQ(IDMN,IJKDM) ! get cut-cell number
IF(IPBC>0.AND.ISKY==0) THEN        ! dealing with cut cell
IT1= ISHPB(IDMN,IPBC)
GH=F(IT1+PBC_SNYDIST)
ELSE
IF(IVDIR==1) THEN     ! up X
IF(ISKY==0) THEN
IB=ITWO(IZ,IY,ITYPE==4.OR.ITYPE==5)
ELSE
IB=(IY-1)*NZ+IZ
ENDIF
ELSEIF(IVDIR==2) THEN ! up Y
IF(ISKY==0) THEN
IB=ITWO(IZ,IX,ITYPE==2.OR.ITYPE==3)
ELSE
IB=(IX-1)*NZ+IZ
ENDIF
ELSE                    ! up Z
IF(ISKY==0) THEN
IB=ITWO(IY,IX,ITYPE==2.OR.ITYPE==3)
ELSE
IB=I
ENDIF
ENDIF
GH=AMAX1(F(L0H+I)-F(L0HI(IDMN,IBLIN)+IB),0.0)
ENDIF
F(L0VAL+I)=VELCON*GH**ALPHA
ELSE
F(L0VAL+I)=0.0
ENDIF
ENDDO
ENDDO
C... log-law profile
C    ---------------
ELSEIF(IBLTY==1) THEN
C.. VELCON = QTAU/KAPPA
IF(ITPRO > 0 .AND. ITPRO /= 4) THEN
VELCON=VELIN/(LOG((REFH-WALLB)/ZO)-PSIF(REFH,GLMO))
ELSE              ! Neutral
VELCON=VELIN/LOG((REFH-WALLB)/ZO)
ENDIF
DO IX=IXF,IXL
DO IY=IYF,IYL
IF(.NOT.SLD(I)) THEN
IJKDM=I+(IZ-1)*NX*NY
IF(PARSOL) IPBC = IPBSEQ(IDMN,IJKDM) ! get cut-cell number
IF(IPBC>0.AND.ISKY==0) THEN          ! dealing with cut cell
IT1= ISHPB(IDMN,IPBC)
GH=F(IT1+PBC_SNYDIST)
ELSE
IF(IVDIR==1) THEN     ! up X
IF(ISKY==0) THEN
IB=ITWO(IZ,IY,ITYPE==4.OR.ITYPE==5)
ELSE
IB=(IY-1)*NZ+IZ
ENDIF
ELSEIF(IVDIR==2) THEN ! up Y
IF(ISKY==0) THEN
IB=ITWO(IZ,IX,ITYPE==2.OR.ITYPE==3)
ELSE
IB=(IX-1)*NZ+IZ
ENDIF
ELSE                    ! up Z
IF(ISKY==0) THEN
IB=ITWO(IY,IX,ITYPE==2.OR.ITYPE==3)
ELSE
IB=I
ENDIF
ENDIF
GH=AMAX1(F(L0H+I)-F(L0HI(IDMN,IBLIN)+IB),0.0)
ENDIF
IF(EQZ(WALLB)) THEN
GHDZO=AMAX1(GH/ZO,2.0)
ELSE
IF(LTZ(WALLB)) THEN
GHDZO=(GH-WALLB)/ZO
ELSE
GHDZO=AMAX1((GH-WALLB)/ZO,2.0)
ENDIF
ENDIF
C.. VELCON = QTAU/KAPPA
IF(ITPRO > 0 .AND. ITPRO /= 4) THEN
F(L0VAL+I)=VELCON*(LOG(GHDZO)-PSIF(GH,GLMO))
ELSE               ! Neutral
F(L0VAL+I)=VELCON*LOG(GHDZO)
ENDIF
ELSE
F(L0VAL+I)=0.0
ENDIF
if(l0velin>0) f(l0velin+i)=f(l0val+i)
ENDDO
ENDDO
ENDIF
C
C... inlet k and ep/omeg values
C    ==========================
C
ELSEIF(INDVAR==KE.OR.INDVAR==EP.OR.INDVAR.EQ.LBOMEG) THEN
L0VAL=L0F(VAL)
IPBC=0
IF(IBLTY==1.OR.IBLTY==2) THEN ! log and power law
REFHMD = REFH-WALLB
IF(ITPRO > 0 .AND. ITPRO /= 4) THEN
QTAU = ABS(AK*QREF/(LOG((REFHMD)/ZO)-PSIF(REFHMD,GLMO)))
ELSE
QTAU = ABS(AK*QREF/(LOG((REFHMD)/ZO)))
ENDIF
QTAU2 = QTAU*QTAU
C... Taudke=cmucd**0.5
GKEIN  = QTAU2/TAUDKE  ! Nb: Taudke=sqrt(CmuCd)
GEPCON = QTAU2*QTAU/AK
IF(INDVAR==KE) THEN
CALL FN1(VAL,GKEIN)
IF(ITPRO > 0 .AND. ITPRO /= 4) THEN
lbkein=lbname('KEIN') ; if(lbkein>0) l0kein=l0f(lbkein)
DO IX=IXF,IXL
DO IY=IYF,IYL
IF(.NOT.SLD(I)) THEN ! open cell
IJKDM=I+(IZ-1)*NX*NY
IF(PARSOL) IPBC = IPBSEQ(IDMN,IJKDM) ! get cut-cell number
IF(IPBC>0.AND.ISKY==0) THEN          ! dealing with cut cell
IT1= ISHPB(IDMN,IPBC)
GH=F(IT1+PBC_SNYDIST)
ELSE
IF(IVDIR==1) THEN     ! up X
IF(ISKY==0) THEN
IB=ITWO(IZ,IY,ITYPE==4.OR.ITYPE==5)
ELSE
IB=(IY-1)*NZ+IZ
ENDIF
ELSEIF(IVDIR==2) THEN ! up Y
IF(ISKY==0) THEN
IB=ITWO(IZ,IX,ITYPE==2.OR.ITYPE==3)
ELSE
IB=(IX-1)*NZ+IZ
ENDIF
ELSE                    ! up Z
IF(ISKY==0) THEN
IB=ITWO(IY,IX,ITYPE==2.OR.ITYPE==3)
ELSE
IB=I
ENDIF
ENDIF
GH=AMAX1(F(L0H+I)-F(L0HI(IDMN,IBLIN)+IB),0.0)
ENDIF
IF(LTZ(WALLB)) THEN
GZMDH=(GH-WALLB)
ELSE
GZMDH=AMAX1(2.0*ZO,(GH-WALLB))
ENDIF
GPHIE = PHIE(GZMDH,GLMO)
GPHIM = 1.0-PSIFT(GZMDH,GLMO)
F(L0VAL+I)=GKEIN*(GPHIE/GPHIM)**0.5
ELSE
F(L0VAL+I)=0.0
ENDIF
if(lbkein>0) f(l0kein+i)=f(l0val+i)
ENDDO
ENDDO
ENDIF
ENDIF
IF(INDVAR==EP.OR.INDVAR.EQ.LBOMEG) THEN
IF(INDVAR==LBOMEG) THEN
lbomin=lbname('OMIN') ; if(lbomin>0) l0omin=l0f(lbomin)
L0OMEG=L0F(LBOMEG)
GOMCON=QTAU/(AK*TAUDKE)
ELSE
lbepin=lbname('EPIN') ; if(lbepin>0) l0epin=l0f(lbepin)
L0EP=L0F(EP)
ENDIF
DO IX=IXF,IXL
DO IY=IYF,IYL
IF(.NOT.SLD(I)) THEN ! open cell
IJKDM=I+(IZ-1)*NX*NY
IF(PARSOL) IPBC = IPBSEQ(IDMN,IJKDM) ! get cut-cell number
IF(IPBC>0.AND.ISKY==0) THEN          ! dealing with cut cell
IT1= ISHPB(IDMN,IPBC)
GH=F(IT1+PBC_SNYDIST)
ELSE
IF(IVDIR==1) THEN     ! up X
IF(ISKY==0) THEN
IB=ITWO(IZ,IY,ITYPE==4.OR.ITYPE==5)
ELSE
IB=(IY-1)*NZ+IZ
ENDIF
ELSEIF(IVDIR==2) THEN ! up Y
IF(ISKY==0) THEN
IB=ITWO(IZ,IX,ITYPE==2.OR.ITYPE==3)
ELSE
IB=(IX-1)*NZ+IZ
ENDIF
ELSE                    ! up Z
IF(ISKY==0) THEN
IB=ITWO(IY,IX,ITYPE==2.OR.ITYPE==3)
ELSE
IB=I
ENDIF
ENDIF
GH=AMAX1(F(L0H+I)-F(L0HI(IDMN,IBLIN)+IB),0.0)
ENDIF
IF(LTZ(WALLB)) THEN
GZMDH=(GH-WALLB)
ELSE
GZMDH=AMAX1(2.0*ZO,(GH-WALLB))
ENDIF
IF(INDVAR==EP) THEN
GEPIN=GEPCON/GZMDH     ! e = ustar^3/(ak*(z-d))
IF(ITPRO > 0 .AND. ITPRO /= 4) THEN
GEPIN=GEPIN*PHIE(GZMDH,GLMO)
ENDIF
F(L0VAL+I)=GEPIN
ELSE IF(INDVAR==LBOMEG) THEN
GOMEGI=GOMCON/GZMDH ! f = ustar/(sqrt(CmuCD)*ak*(z-d))
IF(ITPRO > 0 .AND. ITPRO /= 4) THEN
GPHIE = PHIE(GZMDH,GLMO)
GPHIM = 1.0-PSIFT(GZMDH,GLMO)
F(L0VAL+I)=GOMEGI*(GPHIE*GPHIM)**0.5
ELSE
F(L0VAL+I)=GOMEGI
ENDIF
ENDIF
ELSE
F(L0VAL+I)=0.0
ENDIF
if(indvar==ep.and.lbepin>0) f(l0epin+i)=f(l0val+i)
if(indvar==lbomeg.and.lbomin>0) f(l0omin+i)=f(l0val+i)
ENDDO
ENDDO
ENDIF
ELSE                ! TABLE profile
lbkein=lbname('KEIN')
if(lbkein>0) l0kein=l0f(lbkein)
lbepin=lbname('EPIN')
if(lbepin>0) l0epin=l0f(lbepin)
lbomin=lbname('OMIN')
if(lbomin>0) l0omin=l0f(lbomin)
DO IX=IXF,IXL
DO IY=IYF,IYL
IF(.NOT.SLD(I)) THEN ! open cell
IJKDM=I+(IZ-1)*NX*NY
IF(PARSOL) IPBC = IPBSEQ(IDMN,IJKDM) ! get cut-cell number
IF(IPBC>0.AND.ISKY==0) THEN          ! dealing with cut cell
IT1= ISHPB(IDMN,IPBC)
GH=F(IT1+PBC_SNYDIST)
ELSE
IF(IVDIR==1) THEN     ! up X
IF(ISKY==0) THEN
IB=ITWO(IZ,IY,ITYPE==4.OR.ITYPE==5)
ELSE
IB=(IY-1)*NZ+IZ
ENDIF
ELSEIF(IVDIR==2) THEN ! up Y
IF(ISKY==0) THEN
IB=ITWO(IZ,IX,ITYPE==2.OR.ITYPE==3)
ELSE
IB=(IX-1)*NZ+IZ
ENDIF
ELSE                    ! up Z
IF(ISKY==0) THEN
IB=ITWO(IY,IX,ITYPE==2.OR.ITYPE==3)
ELSE
IB=I
ENDIF
ENDIF
GH=AMAX1(F(L0H+I)-F(L0HI(IDMN,IBLIN)+IB),0.0)
ENDIF
GKEIN=-999. ! initialise
DO IL=1,NLINEK-1
IF(GH>=KE_TAB(IL,1).AND.GH<=KE_TAB(IL+1,1)) THEN ! linear
GKEIN=KE_TAB(IL,2)+(GH-KE_TAB(IL,1))           ! interpolation
1                 *(KE_TAB(IL+1,2)-KE_TAB(IL,2))/
1                  (KE_TAB(IL+1,1)-KE_TAB(IL,1))
EXIT
ENDIF
ENDDO
IF(QEQ(GKEIN,-999.)) THEN ! no value found
IF(GH>=KE_TAB(NLINEK,1)) THEN ! above top of table
GKEIN=KE_TAB(NLINEK,2)      ! use top value
ELSE                          ! below bottom of table
GKEIN=KE_TAB(1,2)           ! use bottom value
ENDIF
ENDIF
IF(INDVAR==KE) THEN
F(L0VAL+I)=GKEIN
ELSEIF (INDVAR==EP) THEN             ! Nb: Cd = (CmuCd)^0.75
F(L0VAL+I)=CD*GKEIN**1.5/(AK*GH)   ! e = Cd*k^1.5/(ak*(z-d))
ELSEIF (INDVAR==LBOMEG) THEN            ! Nb: RTTDKE=SQRT(TAUDKE) & TAUDKE=SQRT(CM
F(L0VAL+I)=SQRT(GKEIN)/(AK*RTTDKE*GH) ! f = sqrt(k)/(ak*(z-d)*(CmuCd)^0.25)
ENDIF
ELSE
F(L0VAL+I)=0.0
ENDIF
if(indvar==ke.and.lbkein>0) f(l0kein+i)=f(l0val+i)
if(indvar==ep.and.lbepin>0) f(l0epin+i)=f(l0val+i)
if(indvar==lbomeg.and.lbomin>0) f(l0omin+i)=f(l0val+i)
ENDDO
ENDDO
ENDIF
C
C... External air temperature
C    ========================
ELSEIF(INDVAR==ITEM1) THEN
IF(ITPRO==0.OR.ITPRO==4) THEN  ! Uniform profile or Neutral
CALL FN1(VAL,TAIR)
ELSE IF(ITPRO > 0 ) THEN
C... Pasquill temperature profiles
lbtin=lbname('TIN')
if(lbtin>0) l0tin=l0f(lbtin)
IF(ITPRO > 0 .AND. ITPRO /= 4) THEN
C.. friction velocity
REFHMD = REFH-WALLB  ! (z-d)
QTAU   = AK*QREF/(LOG((REFHMD)/ZO)-PSIF(REFHMD,GLMO))
C... Friction temperature
GTSTAR= -GQWALL/(RHOIN*CP1*QTAU) ; GTSDAK=GTSTAR/AK
ENDIF
L0VAL=L0F(VAL)
IPBC=0
DO IX=IXF,IXL
DO IY=IYF,IYL
IF(.NOT.SLD(I)) THEN ! open cell
IJKDM=I+(IZ-1)*NX*NY
IF(PARSOL) IPBC = IPBSEQ(IDMN,IJKDM) ! get cut-cell number
IF(IPBC>0.AND.ISKY==0) THEN          ! dealing with cut cell
IT1= ISHPB(IDMN,IPBC)
GH=F(IT1+PBC_SNYDIST)
ELSE
IF(IVDIR==1) THEN     ! up X
IF(ISKY==0) THEN
IB=ITWO(IZ,IY,ITYPE==4.OR.ITYPE==5)
ELSE
IB=(IY-1)*NZ+IZ
ENDIF
ELSEIF(IVDIR==2) THEN ! up Y
IF(ISKY==0) THEN
IB=ITWO(IZ,IX,ITYPE==2.OR.ITYPE==3)
ELSE
IB=(IX-1)*NZ+IZ
ENDIF
ELSE                    ! up Z
IF(ISKY==0) THEN
IB=ITWO(IY,IX,ITYPE==2.OR.ITYPE==3)
ELSE
IB=I
ENDIF
ENDIF
GH=AMAX1(F(L0H+I)-F(L0HI(IDMN,IBLIN)+IB),0.0)
ENDIF
C                    IF(ITPRO==) THEN
C.. linear profile:- T = T0 +gam*(z-z0)
C                      GTLIN = GT0 - GALR*(GH-GZT0)
C                      F(L0VAL+I)= GTLIN
IF(ITPRO > 0 .AND. ITPRO /= 4) THEN ! Pasquill - Stable (LMO > 0)
C.. log profile:-    T = T0-gam*(z-z0)+(T*/k)*log(z/z0)
IF(EQZ(WALLB)) THEN
GHDZO=AMAX1(GH/ZO,2.0)
ELSE
IF(LTZ(WALLB)) THEN
GHDZO=(GH-WALLB)/ZO
ELSE
GHDZO=AMAX1((GH-WALLB)/ZO,2.0)
ENDIF
ENDIF
GTLIN = GT0 - GALR*(GH-GZT0)
GPSIT = PSIFT(GH-WALLB,GLMO)
F(L0VAL+I)=GTLIN+GTSDAK*(LOG(GHDZO)-GPSIT)
ENDIF
ELSE
F(L0VAL+I)=0.0
ENDIF
if(lbtin>0) f(l0tin+i)=f(l0val+i)
ENDDO
ENDDO
ENDIF
C
C... External air humidity
C    =====================
ELSEIF(INDVAR==IHUM) THEN
CALL FN1(VAL,HUMIN)
ENDIF
C
C... Group 13, Section 14 Density-difference buoyancy forces
C
C... Buoyancy Forces
C    ===============
ELSEIF(IGR==13.AND.ISC==14) THEN ! Density difference
C.. Entry here is from GXBUOY with VAL=-g ; Rhoref = f(height)
C   for all velocities, so need to identify active gravity direction
IF(INDVAR==3) THEN
L0VAL= L0F(VAL) ; L0D9 = L0F(LD9)
C          DO I=1,NXNY
C            F(L0VAL+I) = F(L0VAL+I)*(F(L0D9+I) - BUOYD)/F(L0D9+I)
C          ENDDO
L0DEN=L0F(DEN1)
IF(LBRHIN>0) THEN
L0RHIN=L0F(LBRHIN)
ELSE
L0RHIN=(IZ-1)*NXNY+L0RHIN0
ENDIF
GGRAVY=BUOYA
DO JX=1,NX-1
DO JY=1,NY
IF(SLD(J)) THEN
F(L0VAL+J)=0.0
ELSE
GRHO=F(L0DEN+J)
GRHON=F(L0DEN+J+NY)
GRHOAV=0.5*(GRHO+GRHON)
GRHRAV=0.5*(F(L0RHIN+J)+F(L0RHIN+J+NY))
C              GRHOREF = BUOYD
F(L0VAL+J)=(1.-GRHRAV/GRHOAV)*GGRAVY
ENDIF
ENDDO
ENDDO
ELSEIF(INDVAR==5) THEN
L0VAL=L0F(VAL)
L0DEN=L0F(DEN1)
IF(LBRHIN>0) THEN
L0RHIN=L0F(LBRHIN)
ELSE
L0RHIN=(IZ-1)*NXNY+L0RHIN0
ENDIF
GGRAVY=BUOYB
DO JX=1,NX
DO JY=1,NY-1
IF(SLD(J)) THEN
F(L0VAL+J)=0.0
ELSE
GRHO=F(L0DEN+J)
GRHON=F(L0DEN+J+1)
GRHOAV=0.5*(GRHO+GRHON)
GRHRAV=0.5*(F(L0RHIN+J)+F(L0RHIN+J+1))
C              GRHOREF = BUOYD
F(L0VAL+J)=(1.-GRHRAV/GRHOAV)*GGRAVY
ENDIF
ENDDO
ENDDO
ELSEIF(INDVAR==7) THEN
L0VAL=L0F(VAL)  ; L0D9 = L0F(LD9)
L0DEN=L0F(DEN1); L0DENH=L0F(HIGH(DEN1))
IF(LBRHIN>0) THEN
L0RHIN=L0F(LBRHIN); L0RHINH=L0F(HIGH(LBRHIN))
ELSE
L0RHIN=(IZ-1)*NXNY+L0RHIN0
L0RHINH=L0RHIN+NXNY
ENDIF

GGRAVY=BUOYC
DO JX=1,NX
DO JY=1,NY
IF(SLD(J)) THEN
F(L0VAL+J)=0.0
ELSE
GRHO=F(L0DEN+J) ; GRHON=F(L0DENH+J)
GRHOAV=0.5*(GRHO+GRHON)
C.. NB: 1st visit rhin,high=0.0
GRHRAV=0.5*(F(L0RHIN+J)+F(L0RHINH+J))
F(L0VAL+J)=(1.-GRHRAV/GRHOAV)*GGRAVY
ENDIF
ENDDO
ENDDO
ENDIF
C-------------------------------------------------------------------------
C... Group 13, Section 15 Boussinesq buoyancy forces
C
ELSEIF(IGR==13.AND.ISC==15) THEN ! Boussinesq buoyancy
L0TEM1=L0F(ITEM1)
IF(LBTREF>0) THEN
L0TREF=L0F(LBTREF)
ELSE
L0TREF=L0TREF0+(IZ-1)*NXNY
ENDIF
L0VAL= L0F(VAL) ;L0D9 = L0F(LD9)
IF(INDVAR==3) THEN  ! U1
C          DO I=1,NXNY
C            F(L0VAL+I) = F(L0VAL+I)*(F(L0D9+I) - BUOYD)/F(L0D9+I)
C          ENDDO
GGRAVY=BUOYA
DO JX=1,NX-1
DO JY=1,NY
IF(SLD(J)) THEN
F(L0VAL+J)=0.0
ELSE
GTEM=F(L0TEM1+J)
GTEMN=F(L0TEM1+J+NY)
GTEMAV=0.5*(GTEM+GTEMN)
GTRFAV=0.5*(F(L0TREF+J)+F(L0TREF+J+NY))
F(L0VAL+J)=(GTEMAV-GTRFAV)*GGRAVY*DVO1DT
ENDIF
ENDDO
ENDDO
ELSEIF(INDVAR==5) THEN  ! V1
GGRAVY=BUOYB
DO JX=1,NX
DO JY=1,NY-1
IF(SLD(J)) THEN
F(L0VAL+J)=0.0
ELSE
GTEM=F(L0TEM1+J)
GTEMN=F(L0TEM1+J+1)
GTEMAV=0.5*(GTEM+GTEMN)
GTRFAV=0.5*(F(L0TREF+J)+F(L0TREF+J+1))
C              GRHOREF = BUOYD
F(L0VAL+J)=(GTEMAV-GTRFAV)*GGRAVY*DVO1DT
ENDIF
ENDDO
ENDDO
ELSEIF(INDVAR==7) THEN ! W1
L0TEMH=L0F(HIGH(ITEM1))
IF(LBTREF>0) THEN
L0TREFH=L0F(HIGH(LBTREF))
ELSE
L0TREFH=L0TREF+NXNY
ENDIF
GGRAVY=BUOYC
DO JX=1,NX
DO JY=1,NY
IF(SLD(J)) THEN
F(L0VAL+J)=0.0
ELSE
GTEM=F(L0TEM1+J) ; GTEMN=F(L0TEMH+J)
GTEMAV=0.5*(GTEM+GTEMN)
C.. NB: 1st visit rhin,high=0.0
GTRFAV=0.5*(F(L0TREF+J)+F(L0TREFH+J))
F(L0VAL+J)=(GTEMAV-GTRFAV)*GGRAVY*DVO1DT
ENDIF
ENDDO
ENDDO
ENDIF
C-----------------------------------------------------------------------------
ELSEIF(IGR==19.AND.ISC==1) THEN
C... Group 19, Section 1. Start of time step
C... Echo transient variation of wind parameters
IF(ASSOCIATED(WDIR)) THEN
C... A weather file is in use. Scan through data and interpolate
DO I=1,NL
TIM1=(I-1)*3600/NPHOUR; TIM2=I*3600/NPHOUR; DELT=TIM2-TIM1
IF(QGT(TIM,TIM1).AND.QLE(TIM,TIM2)) THEN
ANG=WDIR(I)+(WDIR(I+1)-WDIR(I))*(TIM-TIM1)/DELT
VEL=WSPD(I)+(WSPD(I+1)-WSPD(I))*(TIM-TIM1)/DELT
TAIR=AIRTEMP(I)+(AIRTEMP(I+1)-AIRTEMP(I))*(TIM-TIM1)/DELT
PAIR=ATMPRES(I)+(ATMPRES(I+1)-ATMPRES(I))*(TIM-TIM1)/DELT
IF(IHUM>0) THEN
HUMIN=RELHUM(I)+(RELHUM(I+1)-RELHUM(I))*(TIM-TIM1)/DELT
ENDIF
EXIT
ENDIF
ENDDO
ANG=ANG-AXDIR
IF(ANG<0.0) THEN
ANG=360.0+ANG
C... if wind angle > 360, subtract 360
ELSEIF(ANG>360) THEN
ANG=ANG-360.0
ENDIF
ANGR=ANG*ATAN(1.)/45. ! make radians
IF(IHUM>0) THEN
IF(IHUNIT>0) THEN
IF(IHUNIT==1) THEN ! convert from humidity ratio
HUMIN=1.E-3*HUMIN
ELSEIF(IHUNIT==2) THEN ! convert from relative humidity
PVAP = 1.E-2*HUMIN*PVH2O(TAIR)
GWRAT = 18.015/28.96
RELH=HUMIN ! save for printout
HUMIN = GWRAT*PVAP/(PAIR-PVAP)
ENDIF
HUMIN=HUMIN/(1+HUMIN)    ! convert to mass fraction
ENDIF
ENDIF
C... Reset buoyancy parameters
IF(INIBUOY==1) THEN
IF(QEQ(RHO1,GRND5)) THEN ! Ideal Gas used
IF(NEZ(RHO1A).AND.IHUM==C1) THEN
GASCON=RHO1A*(1-HUMIN)+RHO1B*HUMIN
ELSE
GASCON=1./RHO1B
ENDIF
RHOIN=PAIR/(GASCON*(TAIR+TEMP0))
C.... reset reference density for buoyancy to inlet density
BUOYD=RHOIN
ELSEIF(RHO1>0.0) THEN ! density is constant
C.... reset reference temperature
BUOYE=TAIR
ENDIF
C.... reset PRESS0 to external pressure
PRESS0=PAIR
ENDIF
C... Update values for BLIN patches
DO IDOM=1,NUMDMN
DO IBL=1,NBLIN(IDOM)
IUP=F(L0VDIR(IDOM)+IBL)
IF(IUP==3) THEN     ! Up Z
VELX=-VEL*SIN(ANGR)
VELY=-VEL*COS(ANGR)
VELZ=0.0
ELSEIF(IUP==2) THEN ! Up Y
VELX=-VEL*COS(ANGR)
VELY=0.0
VELZ=-VEL*SIN(ANGR)
ELSE                  ! Up X
VELX=0.0
VELY=-VEL*SIN(ANGR)
VELZ=-VEL*COS(ANGR)
ENDIF
C... Set inlet velocity components
F(L0VELX(IDOM)+IBL)=VELX
F(L0VELY(IDOM)+IBL)=VELY
F(L0VELZ(IDOM)+IBL)=VELZ
C.. Set inlet velocity magnitude at reference height
F(L0QREF(IDMN)+IBL)=VEL
F(L0TAIR(IDMN)+IBL)=TAIR
F(L0PVAL(IDMN)+IBL)=PAIR
IF(QEQ(RHO1,GRND5)) F(L0DENS(IDMN)+IBL)=RHOIN
IF(IHUM>0) F(L0RELH(IDMN)+IBL)=HUMIN
ENDDO
ENDDO
ELSE
C... No Weather file - search for first BLIN active on this time step
DO IP=1,NUMPAT
IBLIN=NINT(F(L0IPAT(IDMN)+IP))
IF(IBLIN>0) THEN
CALL GETPAT(IP,IREG,TYPE,JXF,JXL,JYF,JYL,JZF,JZL,JTF,JTL)
IF(ISTEP>=JTF.AND.ISTEP<=JTL) THEN ! active this time step
PAIR=F(L0PVAL(IDMN)+IBLIN); RHOIN=F(L0DENS(IDMN)+IBLIN)
TAIR=F(L0TAIR(IDMN)+IBLIN); HUMIN=F(L0RELH(IDMN)+IBLIN)
VEL=F(L0QREF(IDMN)+IBLIN); RELH=-999.0
CALL GETSDR(NAMPAT(IP),'WDIR',ANG);ANG=ANG-AXDIR
IF(INIBUOY==1) THEN
PRESS0=PAIR   ! update reference pressure
IF(QEQ(RHO1,GRND5)) THEN ! Ideal Gas
BUOYD=RHOIN ! update reference density
ELSEIF(RHO1>0.0) THEN    ! Constant density
BUOYE=TAIR  ! update reference temperature
ENDIF
ENDIF
EXIT
ENDIF
ENDIF
ENDDO
C... No wind boundary found for this step, so nothing to print
IF(IP>NUMPAT) THEN
WRITE(14,'(''No wind boundary conditions found at step '',
1        I6)') ISTEP
RETURN
ENDIF
ENDIF
C... Echo inputs to RESULT
CALL WRITST
CH1=CHGR_13(TIM); LT=LENGZZ(CH1)
WRITE(LUPR1,'(''  Wind profile data for time step '',I6,
1   '' at time '',A,''s'')') ISTEP, CH1(1:LT)
IHR=INT(TIM/3600.); TIM1=TIM-IHR*3600.; IMN=INT(TIM1/60.)
WRITE(LUPR1,'(''  Elapsed time: '',I4,'' hrs '',I2,'' mins'')'
1                                                        ) IHR,IMN
CH1=CHGR_13(ANG+AXDIR); LT=LENGZZ(CH1)
WRITE(LUPR1,
1   '(''  Wind direction:    '',A,A)') CH1(1:LT),CHAR(176)
CH1=CHGR_13(VEL); LT=LENGZZ(CH1)
WRITE(LUPR1,
1   '(''  Wind speed:        '',A,'' m/s'')')   CH1(1:LT)
IF(ITEM1>0) THEN
CH1=CHGR_13(TAIR); LT=LENGZZ(CH1)
WRITE(LUPR1,
1   '(''  Air temperature:   '',A,A1,''C'')')   CH1(1:LT),CHAR(176)
ENDIF
CH1=CHGR_13(PAIR); LT=LENGZZ(CH1)
WRITE(LUPR1,
1   '(''  External pressure: '',A,'' Pa'')')    CH1(1:LT)
IF(IHUM>0) THEN
IF(IHUNIT==0) THEN     ! mass fraction
CH1=CHGR_13(HUMIN); LT=LENGZZ(CH1)
WRITE(LUPR1,
1   '(''  H2O mass fraction: '',A,''  '')')     CH1(1:LT)
ELSEIF(IHUNIT==1) THEN ! humidity ratio
CH1=CHGR_13(HUMIN*1000.); LT=LENGZZ(CH1)
WRITE(LUPR1,
1   '(''  Humidity ratio:    '',A,'' g/kg'')')  CH1(1:LT)
ELSE                   ! relative humidity
IF(QEQ(RELH,-999.0)) THEN ! recover from mass fraction
HUMIN=AMIN1(1.0,AMAX1(0.0,HUMIN))
IF(QEQ(HUMIN,1.0)) THEN
HRAT=1./TINY
ELSE
HRAT = HUMIN/(1.-HUMIN+1.E-10)
ENDIF
PVSAT = PVH2O(TAIR) ! Water Vapour Saturation Pressure (Pa)
GWRAT = 18.015/28.96
PVAP = HRAT*PAIR/(GWRAT+HRAT) ! Water vapour Pressure (Pa)
RELH = AMAX1(0.0, AMIN1(100.0, 100.*PVAP/PVSAT)) ! Relative humidity (%)
ENDIF
CH1=CHGR_13(RELH); LT=LENGZZ(CH1)
WRITE(LUPR1,
1   '(''  Relative humidity: '',A,'' %'')')  CH1(1:LT)
ENDIF
ENDIF
CH1=CHGR_13(RHOIN); LT=LENGZZ(CH1)
WRITE(LUPR1,
1   '(''  Air density:       '',A,'' kg/m^3'')') CH1(1:LT)
CALL WRITST
ELSEIF(IGR==19.AND.ISC==4) THEN
C============================================================
C... Group 19, Section 4. End of IZ slab
C    Compute Pasquill-F Buoyancy-reference profiles for use
C    in Group 13 buoyancy source terms
C    Entry here from Grex3 only if PASQBUOY=T
C============================================================
IBLIN=1
C.. inlet velocity magnitude at reference height
QREF=F(L0QREF(IDMN)+IBLIN)
C.. inlet temperature
TAIR=F(L0TAIR(IDMN)+IBLIN)
C.. vertical coordinate direction
IVDIR=NINT(F(L0VDIR(IDMN)+IBLIN))
C.. inlet density
RHOIN=F(L0DENS(IDMN)+IBLIN)
C.. effective roughness length
ZO=F(L0ZREF(IDMN)+IBLIN)
C.. reference height for wind reference velocity
REFH=F(L0HREF(IDMN)+IBLIN)
C
ISKY=NINT(F(L0SKY(IDMN)+IBLIN))
C... store vertical height of grid nodes in L0H
IF(IVDIR==1) THEN     ! up X
IF(ISKY==1) THEN
CALL FN0(-L0H,XU2D)
ELSE
CALL FN0(-L0H,XG2D)
ENDIF
ELSEIF(IVDIR==2) THEN ! up Y
IF(ISKY==1) THEN
CALL FN0(-L0H,YV2D)
ELSE
CALL FN0(-L0H,YG2D)
ENDIF
ELSEIF(IVDIR==3) THEN ! up Z
IF(ISKY==1) THEN
GH=F(L0F(ZWNZ)+IZ)
ELSE
GH=F(L0F(ZGNZ)+IZ)
ENDIF
CALL FN1(-L0H,GH)
ENDIF
C
C.. Compute inlet (reference) temperature profile
C   =============================================
IF(LBTREF>0) THEN
L0TREF=L0F(LBTREF)
ELSE
L0TREF=L0TREF0+(IZ-1)*NXNY
ENDIF
C... Reference Temperature
c... Datum is at y=0 ; p=p0 rho=rhoo T=To
GY0  = 0.0   ; GP0  = 0.0
GRGAS= 286.7
GRHO0= (PRESS0+GP0)/(GRGAS*(GT0+TEMP0))
C        GZG  = GH
REFHMD = REFH-WALLB  ! (z-d)
QTAU   = AK*QREF/(LOG((REFHMD)/ZO)-PSIF(REFHMD,GLMO))
GTSTAR= -GQWALL/(RHOIN*CP1*QTAU) ; GTSDAK=GTSTAR/AK
IPBC=0
DO IX=1,NX
DO IY=1,NY
IF(.NOT.SLD(I)) THEN ! open cell
IJKDM=I+(IZ-1)*NX*NY
IF(PARSOL) IPBC = IPBSEQ(IDMN,IJKDM) ! get cut-cell number
IF(IPBC>0.AND.ISKY==0) THEN          ! dealing with cut cell
IT1= ISHPB(IDMN,IPBC)
GH=F(IT1+PBC_SNYDIST)
ELSE
IF(IVDIR==1) THEN     ! up X
IF(ISKY==0) THEN
IB=ITWO(IZ,IY,ITYPE==4.OR.ITYPE==5)
ELSE
IB=(IY-1)*NZ+IZ
ENDIF
ELSEIF(IVDIR==2) THEN ! up Y
IF(ISKY==0) THEN
IB=ITWO(IZ,IX,ITYPE==2.OR.ITYPE==3)
ELSE
IB=(IX-1)*NZ+IZ
ENDIF
ELSE                    ! up Z
IF(ISKY==0) THEN
IB=ITWO(IY,IX,ITYPE==2.OR.ITYPE==3)
ELSE
IB=I
ENDIF
ENDIF
GH=AMAX1(F(L0H+I)-F(L0HI(IDMN,IBLIN)+IB),0.0)
ENDIF
GTLIN = GT0 - GALR*(GH-GZT0)
GPSIT = PSIFT(GH-WALLB,GLMO)
IF(EQZ(WALLB)) THEN
GHDZO=AMAX1(GH/ZO,2.0)
ELSE
IF(LTZ(WALLB)) THEN
GHDZO=(GH-WALLB)/ZO
ELSE
GHDZO=AMAX1((GH-WALLB)/ZO,2.0)
ENDIF
ENDIF
ENDIF
F(L0TREF+I)=GTLIN+GTSDAK*(LOG(GHDZO)-GPSIT)
ENDDO
ENDDO
C
IF(BUOSSG) RETURN
C
C   Density-difference buoyancy profiles
C
C.. Compute inlet (reference) pressure & density profiles
C   =====================================================
IF(LBPIN>0) THEN
L0PIN  = L0F(LBPIN)
L0PINL = L0F(LOW(LBPIN))
ELSE
L0PIN = (IZ-1)*NXNY+L0PIN0
L0PINL = L0PIN-NXNY
ENDIF
IF(LBRHIN>0) THEN
L0RHIN  = L0F(LBRHIN)
L0RHINL = L0F(LOW(LBRHIN))
ELSE
L0RHIN  = (IZ-1)*NXNY+L0RHIN0
L0RHINL = L0RHIN-NXNY
ENDIF
IF(IVDIR==1) THEN     ! Up X
GGRAVY=BUOYA
L0XG = L0F(XG2D)       ; L0DXG=L0F(DXG2D)
C... Pressure & density at first vertical cell
JX=1
DO JY=1,NY
J=(JX-1)*NY+JY
GDYP=F(L0XG+1)
GTERM1 = 0.5*GRHO0*GGRAVY*GDYP
GTERM2 = 0.5*GGRAVY*GDYP/(GRGAS*(F(L0TREF+J)+TEMP0))
F(L0PIN+J)=(GP0+GTERM1)/(1.-GTERM2)
F(L0RHIN+J)=(PRESS0+F(L0PIN+J))/(GRGAS*(F(L0TREF+J)+TEMP0))
ENDDO
C... Remainder of reference pressure & density profiles
DO JX=2,NX
DO JY=1,NY
JS=J-NY
GDYGS=F(L0DXG+JS)
GTERM1 = 0.5*F(L0RHIN+JS)*GGRAVY*GDYGS
GTERM2 = 0.5*GGRAVY*GDYGS/(GRGAS*(F(L0TREF+J)+TEMP0))
F(L0PIN+J)=(F(L0PIN+JS)+GTERM1)/(1.-GTERM2)
F(L0RHIN+J)=(PRESS0+F(L0PIN+J))/(GRGAS*(F(L0TREF+J)+TEMP0))
ENDDO
ENDDO
C
ELSEIF(IVDIR==2) THEN ! Up y
C
GGRAVY=BUOYB
L0YG = L0F(YG2D)       ; L0DYG=L0F(DYG2D)
C... Pressure & density at first vertical cell
DO JX=1,NX
J=(JX-1)*NY+1
GDYP=F(L0YG+1)
GTERM1 = 0.5*GRHO0*GGRAVY*GDYP
GTERM2 = 0.5*GGRAVY*GDYP/(GRGAS*(F(L0TREF+J)+TEMP0))
F(L0PIN+J)=(GP0+GTERM1)/(1.-GTERM2)
F(L0RHIN+J)=(PRESS0+F(L0PIN+J))/(GRGAS*(F(L0TREF+J)+TEMP0))
ENDDO
C... Remainder of reference pressure & density profiles
DO JX=1,NX
DO JY=2,NY
JS=J-1
GDYGS=F(L0DYG+JS)
GTERM1 = 0.5*F(L0RHIN+JS)*GGRAVY*GDYGS
GTERM2 = 0.5*GGRAVY*GDYGS/(GRGAS*(F(L0TREF+J)+TEMP0))
F(L0PIN+J)=(F(L0PIN+JS)+GTERM1)/(1.-GTERM2)
F(L0RHIN+J)=(PRESS0+F(L0PIN+J))/(GRGAS*(F(L0TREF+J)+TEMP0))
ENDDO
ENDDO
C
ELSEIF(IVDIR==3) THEN ! Up z
C
GGRAVY=BUOYC
L0ZG = L0F(ZGNZ)       ; L0DZG=L0F(DZGNZ)
C... Pressure & density at first vertical cell
IF(IZ.EQ.1) THEN
DO J=1,NXNY
GDZP=F(L0ZG+IZ)
GTREF=F(L0TREF+J)
GTERM1 = 0.5*GRHO0*GGRAVY*GDZP
GTERM2 = 0.5*GGRAVY*GDZP/(GRGAS*(F(L0TREF+J)+TEMP0))
F(L0PIN+J)=(GP0+GTERM1)/(1.-GTERM2)
F(L0RHIN+J)=(PRESS0+F(L0PIN+J))/(GRGAS*(GTREF+TEMP0))
ENDDO
C... Remainder of reference pressure & density profiles
ELSE
DO J=1,NXNY
GDZGS=F(L0DZG+IZ-1)
GTERM1 = 0.5*F(L0RHINL+J)*GGRAVY*GDZGS
GTERM2 = 0.5*GGRAVY*GDZGS/(GRGAS*(F(L0TREF+J)+TEMP0))
F(L0PIN+J)=(F(L0PINL+J)+GTERM1)/(1.-GTERM2)
F(L0RHIN+J)=(PRESS0+F(L0PIN+J))/(GRGAS*(F(L0TREF+J)+TEMP0))
ENDDO
ENDIF
C
ENDIF
C-------------------------------------------------------------------------
ELSEIF(IGR==19.AND.ISC==6) THEN
C... Group 19, Section 6. End of IZ slab
C... get velocity amplification factor
IF(LBWAMP>0.OR.LBWAF>0.OR.LBWAT>0.OR.LBCP>0.OR.SHOWCOMF) THEN
C... Calculate and store Wind Velocity Amplification Factor
C... Factor is defined as Absolute velocity / wind speed
IBL=1
ELSE
IBL=IBLIN
ENDIF
ZO=F(L0ZREF(IDMN)+IBL)
IBLTY=NINT(F(L0BLTY(IDMN)+IBL))
QREF=F(L0QREF(IDMN)+IBL)
REFH=F(L0HREF(IDMN)+IBL)
IF(IBLTY==2) ALPHA=F(L0POWR(IDMN)+IBL)
IF(LBWAMP>0) THEN
L0WAMP=L0F(LBWAMP)  ! index for amplification store
ENDIF
IF(LBWAF>0) THEN
L0WAF=L0F(LBWAF); L0ZG=L0F(ZGNZ)
ENDIF
IF(LBWAT>0) THEN
L0WAT=L0F(LBWAT); L0ZG=L0F(ZGNZ)
ENDIF
IF(LBWAF>0.OR.LBWAT>0) THEN
lbvref=lbname('VREF'); lbhref=lbname('HREF')
if(lbvref>0) l0vrf=l0f(lbvref)
if(lbhref>0) l0hrf=l0f(lbhref)
ENDIF
IF(LBVABS>0) THEN ! VABS is stored, so just use it
L0VABS=L0F(LBVABS)
ELSE
L0VABS=L0VAB(IDMN)
L0U=0; L0V=0; L0W=0; L0WL=0
IF(NX>1) L0U=L0F(U1)
IF(NY>1) L0V=L0F(V1)
IF(NZ>1) THEN
L0W=L0F(W1); IF(IZ>1) L0WL=L0F(LOW(W1))
ENDIF
ENDIF
lbghh=lbname('GHH')
if(lbghh>0) l0ghh=l0f(lbghh)
DO IX=1,NX
DO IY=1,NY
I=(IX-1)*NY+IY
IF(LBVABS>0) THEN
VABS=F(L0VABS+I)
ELSE
DU=TINY; UVEL=0.; DV=TINY; VVEL=0.; DW=TINY; WVEL=0.
IF(.NOT.SLD(I)) THEN ! current cell fluid
C... get cell centre velocity as average of E/W, N/S, H/L faces where not blocked
IF(L0U>0) THEN
IF(IX 1) THEN ! not at IX=1
IF(.NOT.SLD(I-NY)) THEN ! West cell fluid
UVEL=UVEL+F(L0U+I-NY); DU=DU+1.
ENDIF
ENDIF
ENDIF
IF(L0V>0) THEN
IF(IY 1) THEN ! not at IY=1
IF(.NOT.SLD(I-1)) THEN ! South cell fluid
VVEL=VVEL+F(L0V+I-1); DV=DV+1.
ENDIF
ENDIF
ENDIF
IF(L0W>0) THEN
IF(IZ 1) THEN ! not at IZ=1
IF(.NOT.SLD(I-NXNY)) THEN ! Low cell fluid
WVEL=WVEL+F(L0WL+I); DW=DW+1.
ENDIF
ENDIF
UVEL=UVEL/DU; VVEL=VVEL/DV; WVEL=WVEL/DW ! average front/back
ENDIF
ENDIF
C... now get absolute velocity and then amplification factor
VABS=(UVEL**2+VVEL**2+WVEL**2)**.5
F(L0VABS+I)=VABS
ENDIF
IF(LBWAMP>0) F(L0WAMP+I)=VABS/(WAMPVR+TINY)
IF(LBWAF>0.OR.LBWAT>0) THEN
GH=F(L0ZG+IZ)-F(L0HIWAF(IDMN)+I)
if(lbghh>0) f(l0ghh+i)=F(L0HIWAF(IDMN)+I)
IF(IBLTY==2) THEN ! power-law profile
WAFVR=QREF*(GH/REFH)**ALPHA
ELSEIF(IBLTY==1) THEN    ! log profile
IF(EQZ(WALLB)) THEN
GHDZO=AMAX1(GH/ZO,2.0)
ELSE
IF(LTZ(WALLB)) THEN
GHDZO=(GH-WALLB)/ZO
ELSE
GHDZO=AMAX1((GH-WALLB)/ZO,2.0)
ENDIF
ENDIF
WAFVR=QREF*LOG(GHDZO)/LOG(REFH/ZO)
ELSE
FACT=-999. ! initialize
DO IL=1,NLINEV-1 ! loop over table
IF(GH>=VEL_TAB(IL,1).AND.GH<=VEL_TAB(IL+1,1)) THEN
FACT=(GH             -VEL_TAB(IL,1))/
1                     (VEL_TAB(IL+1,1)-VEL_TAB(IL,1))
ILP1=IL+1; EXIT
ENDIF
ENDDO
IF(QEQ(FACT,-999.)) THEN ! no value was found
IF(GH>=VEL_TAB(NLINEV,1)) THEN ! above top of table
IL=NLINEV ! use top value
ELSE                           ! below bottom
IL=1      ! use bottom value
ENDIF
FACT=0.0; ILP1=IL
ENDIF
UCOMP=VEL_TAB(IL,2)+FACT*(VEL_TAB(ILP1,2)-
1                                                    VEL_TAB(IL,2))
VCOMP=VEL_TAB(IL,3)+FACT*(VEL_TAB(ILP1,3)-
1                                                    VEL_TAB(IL,3))
WCOMP=VEL_TAB(IL,4)+FACT*(VEL_TAB(ILP1,4)-
1                                                    VEL_TAB(IL,4))
WAFVR=SQRT(UCOMP*UCOMP+VCOMP*VCOMP+WCOMP*WCOMP)
ENDIF
IF(LBWAF>0) F(L0WAF+I)=VABS/(WAFVR+TINY)
IF(LBWAT>0) F(L0WAT+I)=(VABS/(WAFVR+TINY))-1.0
if(lbvref>0) f(l0vrf+i)=WAFvr
if(lbhref>0) f(l0hrf+i)=gh
ENDIF
ENDDO
ENDDO
C... Pressure coefficient
IF(LBCP>0) THEN
QREFSQ=F(L0QREF(IDMN)+IBL)**2 ! current wind speed
L0CP=L0F(LBCP); L0P1=L0F(P1); L0D1=L0F(DEN1)
DO I=1,NXNY
IF(.NOT.SLD(I)) THEN
F(L0CP+I)=F(L0P1+I)/(0.5*F(L0D1+I)*QREFSQ)
ELSE
F(L0CP+I)=0.0
ENDIF
ENDDO
ENDIF
ENDIF
c... Wind comfort
IF(SHOWCOMF) THEN
IF(LBWAMP>0) L0WAMP=L0F(LBWAMP)
IF(LBVAV>0) L0VAV=L0F(LBVAV)
lbwrf=lbname('WRF')
if(lbwrf>0) l0wrf=l0f(lbwrf)
IF(LBPRO>0) L0PRO=L0F(LBPRO)
NEN=TYPECOMF=='NEN8100'; LAWS=TYPECOMF=='LAWSON'
IF(NEN) THEN
L0DAN=L0F(LBDAN); L0NEN=L0F(LBNEN)
UTHR=5.0; DTHR=15.0
ELSEIF(LAWS) THEN
L0LAWS=L0F(LBLAWS)
DO IC=1,6
IF(LBPRB(IC)>0) L0PRB(IC)=L0F(LBPRB(IC))
ENDDO
ENDIF
IF(WEICOEF) THEN  ! Wind data in Weibul coefficients
DO I=1,NXNY
PRO=0.0; IF(NEN) PDAN=0.0
IF(.NOT.SLD(I)) THEN
WRF=F(L0VABS+I)/WMAST
IF(LAWS) THEN ! Lawson criterion
DO IC=1,NCRIT
VINC=LUTHR(IC)/WRF
LPRO(IC,I)=1.-(1.-EXP(-(VINC/AW)**AKW))
if(lbprb(ic)>0) f(l0prb(ic)+i)=LPRO(IC,I)
ENDDO
ELSE ! probability of exceeding or NEN
VINC=UTHR/WRF
PRO=1.-(1.-EXP(-(VINC/AW)**AKW))
IF(NEN) THEN
DINC=DTHR/WRF; PDAN=1.-(1.-EXP(-(DINC/AW)**AKW))
ENDIF
ENDIF
IF(LBVAV>0) THEN ! Sector velocities are stored. Prepare for summing over sectors
F(L0VAV+I)=WRF*VSECT*SECTP ! SECTP is the sector probability
IF(LAWS) THEN ! Lawson
DO IC=1,NCRIT
LPRO(IC,I)=LPRO(IC,I)*SECTP
if(lbprb(ic)>0) f(l0prb(ic)+i)=LPRO(IC,I)
ENDDO
ELSE ! Probability of exceeding or NEN
F(L0PRO+I)=F(L0PRO+I)*SECTP
IF(NEN) F(L0DAN+I)=F(L0DAN+I)*SECTP
ENDIF
ENDIF ! end of SECTP block
ENDIF ! end of .NOT.SLD
IF(.NOT.LAWS) F(L0PRO+I)=PRO; IF(NEN) F(L0DAN+I)=PDAN
ENDDO
ELSE ! Wind data in probability table form
IF(LAWS) LPRO=0.0
DO I=1,NXNY
PRO=0.0; IF(NEN) PDAN=0.0
IF(.NOT.SLD(I)) THEN
WRF=F(L0VABS+I)/WMAST
if(lbwrf>0) f(l0wrf+i)=wrf
DO IB=2,NBINS+1 ! loop over wind speed bins
VI=0.5*(WNDA(IB,1)-WNDA(IB-1,1))+WNDA(IB-1,1) ! mid-bin speed
PROB=WNDA(IB,ISECT+1) ! bin probability
IF(LAWS) THEN ! Lawson
DO IC=1,NCRIT ! loop over criteria
IF(VI*WRF>=LUTHR(IC)) LPRO(IC,I)=LPRO(IC,I)+PROB ! sum probability
if(lbprb(ic)>0) f(l0prb(ic)+i)=LPRO(IC,I)
ENDDO
ELSE ! Probability or NEN
IF(VI*WRF>=UTHR) PRO=PRO+PROB ! sum probability
IF(NEN) THEN; IF(VI*WRF>=DTHR) PDAN=PDAN+PROB; ENDIF
ENDIF
ENDDO ! end loop ovr windspeed bins
IF(.NOT.LAWS) F(L0PRO+I)=PRO; IF(NEN) F(L0DAN+I)=PDAN
IF(LBVAV>0) THEN ! Sector velocities are stored. Prepare for summing over sectors
F(L0VAV+I)=WRF*VSECT*SECTP ! SECTP is the sector probability
IF(LAWS) THEN ! Lawson
DO IC=1,NCRIT
LPRO(IC,I)=LPRO(IC,I)*SECTP
if(lbprb(ic)>0) f(l0prb(ic)+i)=LPRO(IC,I)
ENDDO
ELSE ! Probability of exceeding or NEN
F(L0PRO+I)=F(L0PRO+I)*SECTP
IF(NEN) F(L0DAN+I)=F(L0DAN+I)*SECTP
ENDIF
ENDIF ! end of SECTP block
ENDIF   ! end of .NOT.SLD block
ENDDO     ! end of loop over slab
ENDIF       ! end of probability table block
IF(NEN) THEN ! assign NEN values
DO I=1,NXNY
PRO=F(L0PRO+I); PDAN=F(L0DAN+I)
IF(PRO<0.025) THEN
INEN=1
ELSEIF(PRO>=0.025.AND.PRO<0.05) THEN
INEN=2
ELSEIF(PRO>=0.05.AND.PRO<0.1) THEN
INEN=3
ELSEIF(PRO>=0.1.AND.PRO<0.2) THEN
INEN=4
ELSEIF(PRO>=0.2) THEN
INEN=5
ENDIF
IF(PDAN>=0.05.AND.PDAN<=0.3) THEN
INEN=6
ELSEIF(PDAN>0.3) THEN
INEN=7
ENDIF
F(L0NEN+I)=INEN
ENDDO
ELSEIF(LAWS) THEN ! assign Lawson Criterion valus
DO I=1,NXNY
F(L0LAWS+I)=1
DO IC=NCRIT,1,-1 ! start with most comfortable and work up
IF(LPRO(IC,I)>=LTHRESH(IC)) F(L0LAWS+I)=NCRIT-IC+1
ENDDO
ENDDO
ENDIF ! end of NEN or Lawson
ENDIF   ! end of SHOWCOMF block
ELSEIF(IGR==19.AND.ISC==7) THEN
C... Group 19, Section 7. End of sweep
IF(LBWAF>0.AND.IERR1==0) THEN ! IERR1 is error flag from setting InForm below
CALL HILO3D(LBWAF) ! get domain HI and LO values
IF(MIMD.AND.NPROC>1) THEN
CALL PAR_MAXR(HI3D); CALL PAR_MINR(RLO3D)
ENDIF
CALL SET_INF('WAFM',HI3D,IERR1)
IHI=(IXHI3D-1)*NY+IYHI3D
CALL SET_INF('XWFM',F(L0F(XG2D)+IHI),IERR)
CALL SET_INF('YWFM',F(L0F(YG2D)+IHI),IERR)
CALL SET_INF('ZWFM',F(L0F(ZGNZ)+IZHI3D),IERR)
ENDIF
IF(LBCP>0.AND.IERR2==0) THEN
CALL HILO3D(LBCP) ! get domain HI and LO values
IF(MIMD.AND.NPROC>1) THEN
CALL PAR_MAXR(HI3D); CALL PAR_MINR(RLO3D)
ENDIF
CALL SET_INF('CPM',HI3D,IERR2)
IHI=(IXHI3D-1)*NY+IYHI3D
CALL SET_INF('XCPM',F(L0F(XG2D)+IHI),IERR)
CALL SET_INF('YCPM',F(L0F(YG2D)+IHI),IERR)
CALL SET_INF('ZCPM',F(L0F(ZGNZ)+IZHI3D),IERR)
ENDIF
ELSEIF(IGR==19.AND.ISC==8) THEN
C... Group 19, Section 8. End of time step
IF(ALLOCATED(WNDA)) DEALLOCATE(WNDA,STAT=IERR)
IF(ALLOCATED(VEL_TAB)) DEALLOCATE(VEL_TAB,STAT=IERR)
IF(ALLOCATED(KE_TAB)) DEALLOCATE(KE_TAB,STAT=IERR)
ENDIF
ENDIF
NAMSUB='gxblin'
END
C---------------------------------------------------------------------
SUBROUTINE SEND_FILE(LU,FILNAM,IERR)
INCLUDE 'parear'
CHARACTER FILNAM*(*),CVAL*256, DELIM*1
LOGICAL*4 EXISTS
OPEN(LU,FILE=FILNAM,STATUS='OLD',IOSTAT=IERR)
CALL GLSUMI(IERR)
IF(IERR==0) THEN
CLOSE(LU); RETURN ! file exists on all processors, no need to copy
ENDIF
CALL GETSYSID(ISYSID)
DELIM='/'; IF(ISYSID.LE.2) DELIM=CHAR(92)
II=LAST_INDEX(FILNAM,DELIM) ! find last delimiter
IF(II>0) THEN ! there was one, remove local copies
CVAL=FILNAM(II+1:) ! name without path i.e. local name
OPEN(90,FILE=CVAL,STATUS='OLD',ERR=102) ! does it exist
CLOSE(90,STATUS='DELETE',IOSTAT=IOS)    ! delete if it did
102   CONTINUE
EXISTS=.FALSE. ! flag to copy to master as well as slaves
ELSE ! no delimiter, file is already local
CVAL=FILNAM
IF(MYID>0) THEN ! delete copies on slaves
OPEN(90,FILE=CVAL,STATUS='OLD',ERR=1022) ! does it exist
CLOSE(90,STATUS='DELETE',IOSTAT=IOS)    ! delete if it did
1022     CONTINUE
ENDIF
EXISTS=.TRUE. ! flag to only copy to slaves
ENDIF
II=1 ! now copy central file to local
CALL COPYMOFFILE(II,DELIM,CVAL,FILNAM,IERR,IOS,EXISTS)
END
C--------------------------------------
C Monin-Obukhov similarity-parameter:- psif (momentum)
FUNCTION PSIF(GH,GLMO)
ZETA=GH/GLMO
IF(GLMO.GT.0.0) THEN  ! Stable
PSIF = -5.*ZETA
ELSE                  ! Unstable
PI   = 3.141592654
X    = (1.0-16.*ZETA)**0.25
T1   = 2.*LOG(0.5*(1.0+X))
T2   = LOG(0.5*(1.0+X*X))
PSIF = T1 + T2 - 2.0*ATAN(X)+0.5*PI
ENDIF
END
C Monin-Obukhov similarity-parameter:- psi fif= 1+5*z/L
FUNCTION FIF (GH,GLMO)
ZETA=GH/GLMO
FIF=1+5.*GH/GLMO   ! Stable only
END
C Monin-Obukhov similarity-parameter:- psift (energy)
FUNCTION PSIFT(GH,GLMO)
ZETA=GH/GLMO
IF(GLMO.GT.0.0) THEN ! Stable
PSIFT = -5*ZETA
ELSE                 ! Unstable
X=(1.0-16.*ZETA)**0.25
PSIFT=2.*LOG(0.5*(1.0+X*X))
ENDIF
END
C Monin-Obukhov similarity-parameter:- phie (turbulence)
FUNCTION PHIE(GH,GLMO)
ZETA=GH/GLMO
IF(GLMO.GT.0.0) THEN ! Stable
PHIE = 1.0 + 4.0*ZETA
ELSE                 ! Unstable
PHIE = 1.0 - ZETA
ENDIF
END
```