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), 1 ITEM1,ITEM2,ISPH1,ISPH2,ICON1,ICON2,IPRPS,IRADX,IRADY,IRADZ,IVFOL 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 LOGICAL MASKPT,SLD,QEQ,QGT,QLE,QNE, LPTDMN,LSOLID,EQZ, 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 IF(EPWNAM/=' '.AND..NOT.STEADY) THEN 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(IYSD 0) 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(IXSD 0) 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(IZSD 0) 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(IDMN 1) 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 READ(LU,'(A)',END=105) LINE; LL=LENGZZ(LINE) 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 READ(LU,'(A)') LINE; LL=LENGZZ(LINE) 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 READ(LU,'(A)') LINE 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 READ(LU,'(A)',END=1051) LINE; LL=LENGZZ(LINE) 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 READ(LU,'(A)') LINE ! skip header line 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 READ(LU,'(A)',END=1052) LINE; LL=LENGZZ(LINE) 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 READ(LU,'(A)') LINE ! skip header DO IL=1,NLINEK READ(LU,'(A)') LINE; LL=LENGZZ(LINE) ! read line 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 IADD=NY*(IX-1) DO IY=IYF,IYL I=IY+IADD 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 IADD=NY*(IX-1) DO IY=IYF,IYL I=IY+IADD 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 IADD=NY*(IX-1) DO IY=IYF,IYL I=IY+IADD 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 IADD=NY*(IX-1) DO IY=IYF,IYL I=IY+IADD 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 IADD=NY*(IX-1) DO IY=IYF,IYL I=IY+IADD 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 IADD=NY*(IX-1) DO IY=IYF,IYL I=IY+IADD 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 IADD=NY*(IX-1) DO IY=IYF,IYL I=IY+IADD 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 IADD=NY*(IX-1) DO IY=IYF,IYL I=IY+IADD 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 IADD=NY*(IX-1) DO IY=IYF,IYL I=IY+IADD 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 IADD=NY*(IX-1) DO IY=IYF,IYL I=IY+IADD 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 IADD=NY*(IX-1) DO IY=IYF,IYL I=IY+IADD 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 IADD=NY*(IX-1) DO IY=IYF,IYL I=IY+IADD 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 JXAD=(JX-1)*NY DO JY=1,NY J=JXAD+JY 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 JXAD=(JX-1)*NY DO JY=1,NY-1 J=JXAD+JY 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 JXAD=(JX-1)*NY DO JY=1,NY J=JXAD+JY 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 JXAD=(JX-1)*NY DO JY=1,NY J=JXAD+JY 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 JXAD=(JX-1)*NY DO JY=1,NY-1 J=JXAD+JY 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 JXAD=(JX-1)*NY DO JY=1,NY J=JXAD+JY 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(STEADY) RETURN 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 IADD=NY*(IX-1) DO IY=1,NY I=IY+IADD 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 JXAD=(JX-1)*NY DO JY=1,NY J=JXAD+JY 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 JXAD=(JX-1)*NY DO JY=2,NY J=JXAD+JY 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 IF(STEADY.OR.ASSOCIATED(WDIR)) THEN 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(STEADY.OR.ISTEP==LSTEP) THEN 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