Nodes of different colours represent the following:
Solid arrows point from a parent (sub)module to the submodule which is descended from it. Dashed arrows point from a module being used to the module or program unit using it. Where possible, edges connecting nodes are given different colours to make them easier to distinguish in large graphs.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
integer, | intent(in) | :: | ISurf | |||
integer, | intent(in) | :: | IState | |||
integer, | intent(in) | :: | IConst | |||
type(BSDFWindowGeomDescr), | intent(inout) | :: | Window | |||
type(BSDFGeomDescr), | intent(inout) | :: | Geom | |||
type(BSDFStateDescr), | intent(inout) | :: | State |
Nodes of different colours represent the following:
Solid arrows point from a procedure to one which it calls. Dashed arrows point from an interface to procedures which implement that interface. This could include the module procedures in a generic interface or the implementation in a submodule of an interface in a parent module. Where possible, edges connecting nodes are given different colours to make them easier to distinguish in large graphs.
Nodes of different colours represent the following:
Solid arrows point from a procedure to one which it calls. Dashed arrows point from an interface to procedures which implement that interface. This could include the module procedures in a generic interface or the implementation in a submodule of an interface in a parent module. Where possible, edges connecting nodes are given different colours to make them easier to distinguish in large graphs.
SUBROUTINE SetupComplexWindowStateGeometry (ISurf, IState,IConst,Window,Geom,State)
! SUBROUTINE INFORMATION:
! AUTHOR J. Klems
! DATE WRITTEN June 2011
! MODIFIED na
! RE-ENGINEERED na
! PURPOSE OF THIS SUBROUTINE:
! Define all the geometric quantites for a complex fenestration state
! METHODOLOGY EMPLOYED:
! <description>
! REFERENCES:
! na
! USE STATEMENTS:
USE vectors
IMPLICIT NONE ! Enforce explicit typing of all variables in this routine
! SUBROUTINE ARGUMENT DEFINITIONS:
!INTEGER, INTENT(IN) :: IWind !Complex fenestration number (in window list)
INTEGER, INTENT(IN) :: ISurf !Surface number of the complex fenestration
INTEGER, INTENT(IN) :: IState !State number of the complex fenestration state
INTEGER, INTENT(IN) :: IConst !Pointer to construction for this state
TYPE (BSDFWindowGeomDescr),INTENT(INOUT) :: Window !Window Geometry
TYPE (BSDFGeomDescr), INTENT(INOUT) :: Geom !State Geometry
TYPE (BSDFStateDescr), INTENT(INOUT) :: State !State Description
! SUBROUTINE PARAMETER DEFINITIONS:
! na
! INTERFACE BLOCK SPECIFICATIONS:
! na
! DERIVED TYPE DEFINITIONS:
TYPE BackHitList
INTEGER :: KBkSurf !Back surface index of the hit surface
INTEGER :: HitSurf !Surface number of the hit surface
TYPE (vector) :: HitPt !coords of hit pt (world syst)
REAL(r64) :: HitDsq !Squared distance to the current hit pt
END TYPE BackHitList
! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
REAL(r64) :: Azimuth !Complex fenestration azimuth
REAL(r64) :: Tilt !Complex fenestration tilt
INTEGER :: ElemNo !Grid index variable
INTEGER :: IHit !Surface intersection flag
INTEGER :: I, J !Temp Indices
INTEGER :: IRay !Ray index variable
INTEGER :: IZone !Zone containing the complex window
INTEGER :: JSurf !Secondary Surface index
INTEGER :: BaseSurf !base surface index
INTEGER :: KBkSurf !Back surface index
INTEGER :: MaxHits !Max no of hits found
INTEGER :: MaxInt !Max no of intersections found
INTEGER :: NSky !No of sky rays
INTEGER :: NGnd !No of gnd rays
INTEGER :: NReflSurf !No of rays striking ext surfaces
INTEGER :: NBkSurf !No of back surfaces
INTEGER :: TotHits !Current number of surface intersections
REAL(r64) :: Theta !Basis theta angle
REAL(r64) :: Phi !Basis phi angle
REAL(r64) :: HitDsq !Squared distance to current hit pt
REAL(r64) :: LeastHitDsq !Squared distance to closest hit pt
TYPE (vector) :: HitPt !coords of hit pt (world syst)
REAL(r64),DIMENSION(3) :: V !vector array
REAL(r64) :: VLen !Length of vector array
TYPE (vector) :: X !position vector
TYPE (vector) :: VecNorm !outer normal vector
INTEGER, DIMENSION(:), ALLOCATABLE :: TmpRfSfInd !Temporary RefSurfIndex
INTEGER, DIMENSION(:), ALLOCATABLE :: TmpRfRyNH !Temporary RefRayNHits
INTEGER, DIMENSION(:,:), ALLOCATABLE :: TmpHSurfNo !Temporary HitSurfNo
REAL(r64), DIMENSION(:,:), ALLOCATABLE :: TmpHSurfDSq !Temporary HitSurfDSq
INTEGER, DIMENSION(:), ALLOCATABLE :: TmpSkyInd !Temporary sky index list
INTEGER, DIMENSION(:), ALLOCATABLE :: TmpGndInd !Temporary gnd index list
TYPE (vector), DIMENSION(:), ALLOCATABLE :: TmpGndPt !Temporary ground intersection list
INTEGER, DIMENSION(:,:),ALLOCATABLE :: TmpSurfInt !Temporary index of ray intersecing back surf
REAL(r64), DIMENSION(:,:),ALLOCATABLE :: TmpSjdotN !Temporary dot prod of ray angle w bk surf norm
INTEGER, DIMENSION(:), ALLOCATABLE :: ITemp1D !Temporary INT 1D array
REAL(r64), DIMENSION(:,:), ALLOCATABLE :: Temp2D !Temporary real 2D array
TYPE (vector), DIMENSION(:,:), ALLOCATABLE :: TempV2D !Temporary vector 2D array
TYPE (vector), DIMENSION(:,:), ALLOCATABLE :: TmpHitPt !Temporary HitPt
REAL(r64) :: TransRSurf !Norminal transmittance of shading surface
REAL(r64) :: WtSum !Sum for normalizing various weights
TYPE (BackHitList) :: BSHit !Temp list of back surface hit quantities for a ray
REAL(r64) :: DotProd !Temporary variable for manipulating dot product .dot.
!This routine primarily fills in the BSDFGeomDescr type for a given window and state
!Note that on call the incoming and outgoing basis structure types have already been filled in
!
! Define the central ray directions (in world coordinate system)
!
SurfaceWindow(ISurf)%ComplexFen%State(IState)%NLayers = Construct(IConst)%BSDFInput%NumLayers
Azimuth = DegToRadians * Surface(ISurf)%Azimuth
Tilt = DegToRadians * Surface(ISurf)%Tilt
!For incoming grid
ALLOCATE (Geom%sInc(Geom%Inc%NBasis))
Geom%sInc = vector(0.0d0, 0.0d0, 0.0d0)
ALLOCATE (Geom%pInc(Geom%Inc%NBasis))
ALLOCATE (Geom%CosInc(Geom%Inc%NBasis))
ALLOCATE (Geom%DAInc(Geom%Inc%NBasis))
Geom%pInc = BSDFDaylghtPosition(0.0d0, 0.0d0)
DO ElemNo=1 , Geom%Inc%NBasis
Theta = Geom%Inc%Grid(ElemNo)%Theta
Phi = Geom%Inc%Grid(ElemNo)%Phi
!The following puts in the vectors depending on
! window orientation
Geom%sInc(ElemNo) = WorldVectFromW6 (Theta, Phi, Front_Incident, Tilt, Azimuth)
Geom%pInc(ElemNo) = DaylghtAltAndAzimuth(Geom%sInc(ElemNo))
Geom%CosInc(ElemNo) = COS(Geom%Inc%Grid(ElemNo)%Theta)
!Geom%DAInc(ElemNo) = COS(Geom%pInc(ElemNo)%Altitude) * Geom%Inc%Grid(ElemNo)%dTheta * Geom%Inc%Grid(ElemNo)%dPhi
! Geom%DAInc(ElemNo) = Geom%Inc%Grid(ElemNo)%dTheta * Geom%Inc%Grid(ElemNo)%dPhi
Geom%DAInc(ElemNo) = COS(Geom%Inc%Grid(ElemNo)%Theta) * Geom%Inc%Grid(ElemNo)%dTheta * Geom%Inc%Grid(ElemNo)%dPhi
END DO
! For outgoing grid
ALLOCATE (Geom%sTrn(Geom%Trn%NBasis))
Geom%sTrn = vector(0.0d0, 0.0d0, 0.0d0)
ALLOCATE (Geom%pTrn(Geom%Trn%NBasis))
Geom%pTrn = BSDFDaylghtPosition(0.0d0, 0.0d0)
DO ElemNo=1,Geom%Trn%NBasis
Theta = Geom%Trn%Grid(ElemNo)%Theta
Phi = Geom%Trn%Grid(ElemNo)%Phi
!The following puts in the vectors depending on
! window orientation
Geom%sTrn(ElemNo) = WorldVectFromW6 (Theta, Phi, Front_Transmitted, Tilt, Azimuth)
Geom%pTrn(ElemNo) = DaylghtAltAndAzimuth(Geom%sTrn(ElemNo))
END DO
!
! Incident Basis:
! Construct sky and ground ray index maps, and list of rays intersecting exterior surfaces
!
!Sky, and ground ray index maps, and rays that are potentially beam radiation reflected from exterior surfaces
ALLOCATE(TmpRfSfInd (Geom%Inc%NBasis))
ALLOCATE(TmpRfRyNH (Geom%Inc%NBasis))
ALLOCATE(TmpHSurfNo (Geom%Inc%NBasis,TotSurfaces))
ALLOCATE(TmpHSurfDSq (Geom%Inc%NBasis,TotSurfaces))
ALLOCATE(TmpHitPt (Geom%Inc%NBasis,TotSurfaces))
ALLOCATE(TmpSkyInd (Geom%Inc%NBasis))
ALLOCATE(TmpGndInd(Geom%Inc%NBasis))
ALLOCATE(TmpGndPt(Geom%Inc%NBasis))
NSky = 0
NGnd = 0
NReflSurf = 0
TmpRfRyNH = 0
Geom%NSkyUnobs = 0
Geom%NGndUnobs = 0
! Note--this loop could be repeated for different positions in the window plane (as for detailed reflection
! calculations, varying the origin in the call to PierceSurface. Essentially, have set NsubV =1.
DO IRay = 1, Geom%Inc%NBasis
IF (Geom%sInc(IRay)%z < 0.0d0) THEN
! A ground ray
Geom%NGndUnobs = Geom%NGndUnobs + 1
ELSE
! A sky ray
Geom%NSkyUnobs = Geom%NSkyUnobs + 1
ENDIF
!
! Exterior reveal shadowing/reflection treatment should be inserted here
!
IHit = 0
TotHits = 0
DO JSurf = 1, TotSurfaces
! the following test will cycle on anything except exterior surfaces and shading surfaces
IF( Surface(JSurf)%HeatTransSurf .AND. Surface(JSurf)%ExtBoundCond /= ExternalEnvironment) CYCLE
! skip the base surface containing the window and any other subsurfaces of that surface
IF( JSurf == Surface(ISurf)%BaseSurf .OR. Surface(JSurf)%BaseSurf == Surface(ISurf)%BaseSurf) CYCLE
! skip surfaces that face away from the window
DotProd = Geom%sInc(IRay) .dot. Surface(JSurf)%NewellSurfaceNormalVector
IF( DotProd >= 0.0d0 ) CYCLE
CALL PierceSurfaceVector(JSurf, Surface(ISurf)%Centroid, Geom%sInc(IRay), IHit, HitPt)
IF (IHit <= 0) CYCLE
IHit = 0 !A hit, clear the hit flag for the next cycle
IF(TotHits == 0 ) THEN
! First hit for this ray
TotHits = 1
NReflSurf=NReflSurf + 1
TmpRfSfInd(NReflSurf) = IRay
TmpRfRyNH (NReflSurf) = 1
TmpHSurfNo (NReflSurf,1) = JSurf
TmpHitPt (NReflSurf,1) = HitPt
V = HitPt - Surface(ISurf)%Centroid !vector array from window ctr to hit pt
LeastHitDsq = DOT_PRODUCT (V , V) !dist^2 window ctr to hit pt
TmpHSurfDSq (NReflSurf , 1) = LeastHitDsq
IF(.NOT.Surface(JSurf)%HeatTransSurf .AND. Surface(JSurf)%SchedShadowSurfIndex /= 0) THEN
TransRSurf = 1.0d0 !If a shadowing surface may have a scheduled transmittance,
! treat it here as completely transparent
ELSE
TransRSurf= 0.0d0
ENDIF
ELSE
V = HitPt - Surface(ISurf)%Centroid
HitDsq = DOT_PRODUCT (V , V)
IF (HitDsq >= LeastHitDsq) THEN
IF (TransRSurf > 0.0d0) THEN !forget the new hit if the closer hit is opaque
J = TotHits + 1
IF ( TotHits > 1) THEN
DO I = 2, TotHits
IF ( HitDsq < TmpHSurfDSq(NReflSurf , I) ) THEN
J = I
EXIT
ENDIF
ENDDO
IF(.NOT.Surface(JSurf)%HeatTransSurf .AND. Surface(JSurf)%SchedShadowSurfIndex == 0) THEN
! The new hit is opaque, so we can drop all the hits further away
TmpHSurfNo (NReflSurf , J) = JSurf
TmpHitPt (NReflSurf , J) = HitPt
TmpHSurfDSq (NReflSurf , J) = HitDsq
TotHits = J
ELSE
! The new hit is scheduled (presumed transparent), so keep the more distant hits
! Note that all the hists in the list will be transparent except the last,
! which may be either transparent or opaque
IF (TotHits >= J ) THEN
DO I = TotHits , J , -1
TmpHSurfNo (NReflSurf , I+1) = TmpHSurfNo (NReflSurf , I)
TmpHitPt (NReflSurf , I+1) = TmpHitPt (NReflSurf , I)
TmpHSurfDSq (NReflSurf , I+1) = TmpHSurfDSq (NReflSurf , I)
ENDDO
TmpHSurfNo (NReflSurf , J) = JSurf
TmpHitPt (NReflSurf , J) = HitPt
TmpHSurfDSq (NReflSurf , J) = HitDsq
TotHits = TotHits + 1
ENDIF
ENDIF
ENDIF
ENDIF
ELSE
! A new closest hit. If it is opaque, drop the current hit list,
! otherwise add it at the front
LeastHitDsq = HitDsq
IF(.NOT.Surface(JSurf)%HeatTransSurf .AND. Surface(JSurf)%SchedShadowSurfIndex /= 0) THEN
TransRSurf = 1.0d0 ! New closest hit is transparent, keep the existing hit list
DO I = TotHits , 1 , -1
TmpHSurfNo (NReflSurf , I+1) = TmpHSurfNo (NReflSurf , I)
TmpHitPt (NReflSurf , I+1) = TmpHitPt (NReflSurf , I)
TmpHSurfDSq (NReflSurf , I+1) = TmpHSurfDSq (NReflSurf , I)
TotHits = TotHits + 1
ENDDO
ELSE
TransRSurf = 0.0d0 !New closest hit is opaque, drop the existing hit list
TotHits = 1
ENDIF
TmpHSurfNo (NReflSurf,1) = JSurf ! In either case the new hit is put in position 1
TmpHitPt (NReflSurf,1) = HitPt
TmpHSurfDSq (NReflSurf , 1) = LeastHitDsq
ENDIF
ENDIF
END DO !End of loop over surfaces
IF (TotHits <= 0 ) THEN
!This ray reached the sky or ground unobstructed
IF (Geom%sInc(IRay)%z < 0.0d0) THEN
!A ground ray
NGnd = NGnd + 1
TmpGndInd(NGnd) = IRay
TmpGndPt( NGnd)%x =Surface(ISurf)%Centroid%x - &
( Geom%sInc(IRay)%x / Geom%sInc(IRay)%z) * Surface(ISurf)%Centroid%z
TmpGndPt( NGnd)%y =Surface(ISurf)%Centroid%y - &
( Geom%sInc(IRay)%y / Geom%sInc(IRay)%z) * Surface(ISurf)%Centroid%z
TmpGndPt( NGnd)%z = 0.0d0
ELSE
!A sky ray
NSky = NSky +1
TmpSkyInd(NSky) = IRay
ENDIF
ELSE
!Save the number of hits for this ray
TmpRfRyNH (NReflSurf) = TotHits
ENDIF
END DO !End of loop over basis rays
!
!Store results of indexing the incident basis for this window
!
Geom%NSky = NSky
Geom%NGnd = NGnd
Geom%NReflSurf = NReflSurf
ALLOCATE (Geom%SkyIndex(NSky))
Geom%SkyIndex = TmpSkyInd(1:NSky)
DEALLOCATE (TmpSkyInd)
ALLOCATE( Geom%GndIndex(NGnd) , Geom%GndPt(NGnd) )
Geom%GndIndex = TmpGndInd(1:NGnd)
Geom%GndPt = TmpGndPt(1:NGnd)
DEALLOCATE(TmpGndInd,TmpGndPt)
MaxHits = MAXVAL(TmpRfRyNH)
ALLOCATE(Geom%RefSurfIndex(NReflSurf),Geom%RefRayNHits(NReflSurf))
ALLOCATE(Geom%HitSurfNo(NReflSurf,MaxHits),Geom%HitSurfDSq(NReflSurf,MaxHits))
ALLOCATE(Geom%HitPt(NReflSurf,MaxHits))
Geom%RefSurfIndex = TmpRfSfInd(1:NReflSurf)
Geom%RefRayNHits = TmpRfRyNH(1:NReflSurf)
Geom%HitSurfNo = 0
Geom%HitSurfDSq = 0.0d0
Geom%HitPt = vector(0.0d0,0.0d0,0.0d0)
DO I = 1 , NReflSurf
TotHits = TmpRfRyNH(I)
Geom%HitSurfNo(I,1:TotHits) = TmpHSurfNo(I,1:TotHits)
Geom%HitSurfDSq(I,1:TotHits) = TmpHSurfDSq(I,1:TotHits)
Geom%HitPt( I , 1:TotHits) = TmpHitPt ( I , 1:TotHits)
ENDDO
DEALLOCATE(TmpRfRyNH,TmpRfSfInd,TmpHSurfNo,TmpHSurfDSq,TmpHitPt)
!
!In above scheme sky and ground rays are those that intesect no exterior surfaces.
! The list of hit points is compiled for later (future?) calculation
! of reflections from these surfaces. The hit list for each ray includes all
! surfaces with schedulable transmittance intersected by the ray,
! in order of increasing distance, up to the first opaque surface.
! Rays that intesect one or more schedulable transmittance but no opaque
! surfaces (therefore may reach the sky or ground) are left out of the sky/ground
! calcuation. A correction for these rays could/should be made after the
! shading calculation.
!
!
! Now calculate weights for averaging the transmittance matrix
!
!
!Sky Weights
!
ALLOCATE(Geom%SolSkyWt(NSky))
DO I = 1, NSky
J = Geom%SkyIndex(I)
Geom%SolSkyWt(I) = SkyWeight(Geom%sInc(J))
ENDDO
WtSum = SUM(Geom%SolSkyWt(1:NSky))
Geom%SolSkyWt(1:NSky) = Geom%SolSkyWt(1:NSky)/WtSum
!
!SkyGround Weights
!
ALLOCATE(Geom%SolSkyGndWt(NGnd))
DO I = 1, NGnd
Geom%SolSkyGndWt(I) = SkyGndWeight(Geom%GndPt(I))
ENDDO
WtSum = SUM(Geom%SolSkyGndWt(1:NGnd))
Geom%SolSkyGndWt(1:NGnd) = Geom%SolSkyGndWt(1:NGnd)/WtSum
! Weights for beam reflected from ground are calculated after shading
! interval is determined
!
!Transmitted Basis:
! Construct back surface intersection maps
!
IZone = Surface(ISurf)%Zone
NBkSurf = Window%NBkSurf
ALLOCATE(Geom%NSurfInt(NBkSurf))
Geom%NSurfInt = 0 !Initialize the number of intersections to zero
ALLOCATE(TmpSurfInt(NBkSurf , Geom%Trn%NBasis))
ALLOCATE(TmpSjdotN(NBkSurf , Geom%Trn%NBasis))
!Find the intersections of the basis rays with the back surfaces
DO IRay = 1 , Geom%Trn%NBasis !ray loop
IHit = 0
TotHits = 0
!
! Insert treatment of intersection & reflection from interior reveals here
!
DO KBkSurf = 1 , NBkSurf !back surf loop
BaseSurf = Surface(ISurf)%BaseSurf !ShadowComb is organized by base surface
JSurf = ShadowComb(BaseSurf)%BackSurf(KBkSurf) !these are all proper back surfaces
CALL PierceSurfaceVector(JSurf, Surface(ISurf)%Centroid, Geom%sTrn(IRay), IHit, HitPt)
IF (IHit <= 0) CYCLE
IHit = 0 !A hit, clear the hit flag for the next cycle
IF(TotHits == 0 ) THEN
! First hit for this ray
TotHits=1
BSHit%KBkSurf = KBkSurf
BSHit%HitSurf = JSurf
BSHit%HitPt = HitPt
V = HitPt - Surface(ISurf)%Centroid
BSHit%HitDSq = DOT_PRODUCT ( V , V )
ELSE IF (BSHit%HitSurf == Surface(JSurf)%BaseSurf) THEN
! another hit, check whether this is a subsurface of a previously hit base surface
! (which would be listed first in the Surface array)
! if so, replace the previous hit with this one
TotHits=TotHits + 1
BSHit%KBkSurf = KBkSurf
BSHit%HitSurf = JSurf
BSHit%HitPt = HitPt
V = HitPt - Surface(ISurf)%Centroid
BSHit%HitDSq = DOT_PRODUCT ( V , V )
ELSE
TotHits=TotHits + 1
! is the new hit closer than the previous one (i.e., zone not strictly convex)?
! if so, take the closer hit
V = HitPt - Surface(ISurf)%Centroid
HitDSq = DOT_PRODUCT ( V , V )
IF (HitDSq < BSHit%HitDSq) THEN
BSHit%KBkSurf = KBkSurf
BSHit%HitSurf = JSurf
BSHit%HitPt = HitPt
BSHit%HitDSq = HitDSq
ENDIF
ENDIF
ENDDO !back surf loop
IF (TotHits == 0) THEN !this should not happen--means a ray has gotten lost
! CALL ShowWarningError ('BSDF--Zone surfaces do not completely enclose zone--transmitted ray lost')
ELSE
KBkSurf = BSHit%KBkSurf
JSurf = BSHit%HitSurf
Geom%NSurfInt( KBkSurf ) = Geom%NSurfInt( KBkSurf ) +1
TmpSurfInt(KBkSurf , Geom%NSurfInt( KBkSurf )) = IRay
VecNorm = Surface(JSurf)%OutNormVec
TmpSjdotN(KBkSurf , Geom%NSurfInt( KBkSurf )) = Geom%sTrn(IRay) .dot. VecNorm
ENDIF
ENDDO !ray loop
! All rays traced, now put away the results in the temporary arrays
MaxInt = MAXVAL( Geom%NSurfInt )
ALLOCATE(Geom%SurfInt(Window%NBkSurf , MaxInt))
ALLOCATE(Geom%SjdotN(Window%NBkSurf , MaxInt))
Geom%SurfInt = 0
DO I = 1 , Window%NBkSurf
Geom%SurfInt(I,1:Geom%NSurfInt(I)) = TmpSurfInt(I, 1:Geom%NSurfInt(I))
Geom%SjdotN(I,1:Geom%NSurfInt(I)) = TmpSjdotN(I, 1:Geom%NSurfInt(I))
END DO
DEALLOCATE(TmpSurfInt)
DEALLOCATE(TmpSjdotN)
RETURN
END SUBROUTINE SetupComplexWindowStateGeometry