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) | :: | SurfNum | |||
integer, | intent(in) | :: | NSides | |||
real(kind=r64), | intent(in), | DIMENSION(1:NSides*3) | :: | Vertices |
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 GetVertices(SurfNum,NSides,Vertices)
! SUBROUTINE INFORMATION:
! AUTHOR Linda Lawrie
! DATE WRITTEN May 2000
! MODIFIED na
! RE-ENGINEERED na
! PURPOSE OF THIS SUBROUTINE:
! This subroutine gets the surface vertices from the arrays
! passed by the calling routine. These had previously been obtained
! from the InputProcessor (GetObjectItem). This routine will provide
! a standard place for determining various properties of the surface
! from the vertices.
! METHODOLOGY EMPLOYED:
! na
! REFERENCES:
! na
! USE STATEMENTS:
USE Vectors
USE General, ONLY: RoundSigDigits
USE DataErrorTracking
IMPLICIT NONE ! Enforce explicit typing of all variables in this routine
! SUBROUTINE ARGUMENT DEFINITIONS:
INTEGER, INTENT(IN) :: SurfNum ! Current surface number
INTEGER, INTENT(IN) :: NSides ! Number of sides to figure
REAL(r64), INTENT(IN), DIMENSION(1:NSides*3) :: Vertices ! Vertices, in specified order
! SUBROUTINE PARAMETER DEFINITIONS:
CHARACTER(len=*), PARAMETER :: RoutineName='GetVertices: '
character(len=*), parameter :: fmt3="(A,I5,A,3(1x,f18.13))"
TYPE (vector), PARAMETER :: TestVector=vector(0.0d0,0.0d0,1.0d0)
! INTERFACE BLOCK SPECIFICATIONS
! na
! DERIVED TYPE DEFINITIONS
! na
! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
INTEGER Ptr ! Pointer into Vertice array
INTEGER N ! Loop counter
INTEGER NSrc ! Used for CW -> CCW transformation
INTEGER NTar ! Used for CW -> CCW transformation
REAL(r64) SurfWorldAz
REAL(r64) SurfTilt
REAL(r64) :: Perimeter ! Perimeter length of the surface
INTEGER Vrt ! Used for calculating perimeter
TYPE (vector) :: temp
REAL(r64) :: Xb ! Intermediate calculation
REAL(r64) :: Yb ! Intermediate calculation
INTEGER :: ZoneNum
INTEGER :: ThisCorner
CHARACTER(len=10) :: TiltString
REAL(r64) ThisWidth
REAL(r64) ThisHeight
REAL(r64) :: DistanceCheck
!unused REAL(r64) :: ccwtest
!unused LOGICAL :: SurfaceCCW
REAL(r64) :: dotp
IF (NSides > MaxVerticesPerSurface) MaxVerticesPerSurface=NSides
Ptr=1
DO N=1,NSides
SurfaceTmp(SurfNum)%Vertex(N)%X=Vertices(Ptr)
Ptr=Ptr+1
SurfaceTmp(SurfNum)%Vertex(N)%Y=Vertices(Ptr)
Ptr=Ptr+1
SurfaceTmp(SurfNum)%Vertex(N)%Z=Vertices(Ptr)
Ptr=Ptr+1
ENDDO
! Address changing vertices if they were put in in CW order rather than CCW
IF (.not. CCW) THEN
! If even number of sides, this will transfer appropriately
! If odd number, will leave the "odd" one, which is what you want.
NSrc=NSides
NTar=2
DO N=1,(NSides-1)/2
temp=SurfaceTmp(SurfNum)%Vertex(NSrc)
SurfaceTmp(SurfNum)%Vertex(NSrc)=SurfaceTmp(SurfNum)%Vertex(NTar)
SurfaceTmp(SurfNum)%Vertex(NTar)=temp
NSrc=NSrc-1
NTar=NTar+1
ENDDO
ENDIF
! Now address which "Corner" has been put in first. Note: the azimuth and tilt and area
! calculations do not care which corner is put in first.
! 2/2011 - don't think the shading calculations have a corner preference. Will keep this for
! consistency (for now)
ThisCorner=Corner
DO WHILE (ThisCorner /= UpperLeftCorner)
IF (NSides < 4) THEN
IF (ThisCorner == UpperRightCorner) THEN
ThisCorner=UpperLeftCorner
EXIT
ENDIF
ENDIF
NTar=ThisCorner
NSrc=ThisCorner+1
IF (NSrc > NSides) NSrc=1
DO N=1,NSides-1
temp=SurfaceTmp(SurfNum)%Vertex(NTar)
SurfaceTmp(SurfNum)%Vertex(NTar)=SurfaceTmp(SurfNum)%Vertex(NSrc)
SurfaceTmp(SurfNum)%Vertex(NSrc)=temp
NTar=NTar+1
NSrc=NSrc+1
IF (NTar > NSides) NTar=1
IF (NSrc > NSides) NSrc=1
ENDDO
ThisCorner=ThisCorner+1
IF (ThisCorner > NSides) ThisCorner=1
ENDDO ! Corners
IF (.not. WorldCoordSystem) THEN
! Input in "relative" coordinates, use Building and Zone North Axes and Origins
! to translate each point (including rotation for Appendix G)
ZoneNum=SurfaceTmp(SurfNum)%Zone
IF (ZoneNum > 0) THEN
DO N=1,NSides
Xb = SurfaceTmp(SurfNum)%Vertex(N)%X*CosZoneRelNorth(ZoneNum) &
-SurfaceTmp(SurfNum)%Vertex(N)%Y*SinZoneRelNorth(ZoneNum) + Zone(ZoneNum)%OriginX
Yb = SurfaceTmp(SurfNum)%Vertex(N)%X*SinZoneRelNorth(ZoneNum) &
+SurfaceTmp(SurfNum)%Vertex(N)%Y*CosZoneRelNorth(ZoneNum) + Zone(ZoneNum)%OriginY
SurfaceTmp(SurfNum)%Vertex(N)%X = Xb*CosBldgRelNorth - Yb*SinBldgRelNorth
SurfaceTmp(SurfNum)%Vertex(N)%Y = Xb*SinBldgRelNorth + Yb*CosBldgRelNorth
SurfaceTmp(SurfNum)%Vertex(N)%Z = SurfaceTmp(SurfNum)%Vertex(N)%Z + Zone(ZoneNum)%OriginZ
ENDDO
ELSEIF (SurfaceTmp(SurfNum)%Class == SurfaceClass_Detached_B) THEN
DO N=1,NSides
Xb = SurfaceTmp(SurfNum)%Vertex(N)%X
Yb = SurfaceTmp(SurfNum)%Vertex(N)%Y
SurfaceTmp(SurfNum)%Vertex(N)%X = Xb*CosBldgRelNorth - Yb*SinBldgRelNorth
SurfaceTmp(SurfNum)%Vertex(N)%Y = Xb*SinBldgRelNorth + Yb*CosBldgRelNorth
ENDDO
ENDIF
ELSE
!if world coordinate only need to rotate for Appendix G
ZoneNum=SurfaceTmp(SurfNum)%Zone
IF (ZoneNum > 0) THEN
DO N=1,NSides
Xb = SurfaceTmp(SurfNum)%Vertex(N)%X
Yb = SurfaceTmp(SurfNum)%Vertex(N)%Y
SurfaceTmp(SurfNum)%Vertex(N)%X = Xb*CosBldgRotAppGonly - Yb*SinBldgRotAppGonly
SurfaceTmp(SurfNum)%Vertex(N)%Y = Xb*SinBldgRotAppGonly + Yb*CosBldgRotAppGonly
ENDDO
ELSEIF (SurfaceTmp(SurfNum)%Class == SurfaceClass_Detached_B) THEN
DO N=1,NSides
Xb = SurfaceTmp(SurfNum)%Vertex(N)%X
Yb = SurfaceTmp(SurfNum)%Vertex(N)%Y
SurfaceTmp(SurfNum)%Vertex(N)%X = Xb*CosBldgRotAppGonly - Yb*SinBldgRotAppGonly
SurfaceTmp(SurfNum)%Vertex(N)%Y = Xb*SinBldgRotAppGonly + Yb*CosBldgRotAppGonly
ENDDO
END IF
ENDIF
IF (NSides > 2) THEN
DistanceCheck=Distance(SurfaceTmp(SurfNum)%Vertex(SurfaceTmp(SurfNum)%Sides),SurfaceTmp(SurfNum)%Vertex(1))
IF (DistanceCheck < .01d0) THEN
IF (DisplayExtraWarnings) THEN
CALL ShowWarningError(RoutineName//'Distance between two vertices < .01, possibly coincident.'// &
' for Surface='//TRIM(SurfaceTmp(SurfNum)%Name)// &
', in Zone='//TRIM(SurfaceTmp(SurfNum)%ZoneName))
CALL ShowContinueError('Vertex ['//trim(RoundSigDigits(SurfaceTmp(SurfNum)%Sides))// &
']=('//trim(RoundSigDigits(SurfaceTmp(SurfNum)%Vertex(SurfaceTmp(SurfNum)%Sides)%x,2))//','// &
trim(RoundSigDigits(SurfaceTmp(SurfNum)%Vertex(SurfaceTmp(SurfNum)%Sides)%y,2))//','// &
trim(RoundSigDigits(SurfaceTmp(SurfNum)%Vertex(SurfaceTmp(SurfNum)%Sides)%z,2))//')')
CALL ShowContinueError('Vertex ['//trim(RoundSigDigits(1))// &
']=('//trim(RoundSigDigits(SurfaceTmp(SurfNum)%Vertex(1)%x,2))//','// &
trim(RoundSigDigits(SurfaceTmp(SurfNum)%Vertex(1)%y,2))//','// &
trim(RoundSigDigits(SurfaceTmp(SurfNum)%Vertex(1)%z,2))//')')
ENDIF
TotalCoincidentVertices=TotalCoincidentVertices+1
IF (SurfaceTmp(SurfNum)%Sides > 3) THEN
IF (DisplayExtraWarnings) THEN
CALL ShowContinueError('Dropping Vertex ['//trim(RoundSigDigits(SurfaceTmp(SurfNum)%Sides))//'].')
ENDIF
SurfaceTmp(SurfNum)%Sides=SurfaceTmp(SurfNum)%Sides-1
ELSE
IF (DisplayExtraWarnings) THEN
CALL ShowContinueError('Cannot Drop Vertex ['//trim(RoundSigDigits(SurfaceTmp(SurfNum)%Sides))//']; '// &
'Number of Surface Sides at minimum. This surface is now a degenerate surface.')
ENDIF
TotalDegenerateSurfaces=TotalDegenerateSurfaces+1
! mark degenerate surface?
ENDIF
DistanceCheck=0.0d0
ENDIF
Perimeter=DistanceCheck
! DO Vrt=2,SurfaceTmp(SurfNum)%Sides
Vrt=2
DO
DistanceCheck=Distance(SurfaceTmp(SurfNum)%Vertex(Vrt),SurfaceTmp(SurfNum)%Vertex(Vrt-1))
IF (DistanceCheck < .01d0) THEN
IF (DisplayExtraWarnings) THEN
CALL ShowWarningError(RoutineName//'Distance between two vertices < .01, possibly coincident.'// &
' for Surface='//TRIM(SurfaceTmp(SurfNum)%Name)// &
', in Zone='//TRIM(SurfaceTmp(SurfNum)%ZoneName))
CALL ShowContinueError('Vertex ['//trim(RoundSigDigits(Vrt))// &
']=('//trim(RoundSigDigits(SurfaceTmp(SurfNum)%Vertex(Vrt)%x,2))//','// &
trim(RoundSigDigits(SurfaceTmp(SurfNum)%Vertex(Vrt)%y,2))//','// &
trim(RoundSigDigits(SurfaceTmp(SurfNum)%Vertex(Vrt)%z,2))//')')
CALL ShowContinueError('Vertex ['//trim(RoundSigDigits(Vrt-1))// &
']=('//trim(RoundSigDigits(SurfaceTmp(SurfNum)%Vertex(Vrt-1)%x,2))//','// &
trim(RoundSigDigits(SurfaceTmp(SurfNum)%Vertex(Vrt-1)%y,2))//','// &
trim(RoundSigDigits(SurfaceTmp(SurfNum)%Vertex(Vrt-1)%z,2))//')')
ENDIF
TotalCoincidentVertices=TotalCoincidentVertices+1
IF (Vrt == SurfaceTmp(SurfNum)%Sides) THEN
IF (SurfaceTmp(SurfNum)%Sides > 3) THEN
IF (DisplayExtraWarnings) THEN
CALL ShowContinueError('Dropping Vertex ['//trim(RoundSigDigits(SurfaceTmp(SurfNum)%Sides))//'].')
ENDIF
SurfaceTmp(SurfNum)%Sides=SurfaceTmp(SurfNum)%Sides-1
ELSE
IF (DisplayExtraWarnings) THEN
CALL ShowContinueError('Cannot Drop Vertex ['//trim(RoundSigDigits(SurfaceTmp(SurfNum)%Sides))//']; '// &
'Number of Surface Sides at minimum. This surface is now a degenerate surface.')
ENDIF
TotalDegenerateSurfaces=TotalDegenerateSurfaces+1
! mark degenerate surface?
ENDIF
DistanceCheck=0.0d0
ELSE
IF (SurfaceTmp(SurfNum)%Sides > 3) THEN
IF (DisplayExtraWarnings) THEN
CALL ShowContinueError('Dropping Vertex ['//trim(RoundSigDigits(Vrt))//'].')
ENDIF
DO N=Vrt,SurfaceTmp(SurfNum)%Sides-1
SurfaceTmp(SurfNum)%Vertex(N)%x=SurfaceTmp(SurfNum)%Vertex(N+1)%x
SurfaceTmp(SurfNum)%Vertex(N)%y=SurfaceTmp(SurfNum)%Vertex(N+1)%y
SurfaceTmp(SurfNum)%Vertex(N)%z=SurfaceTmp(SurfNum)%Vertex(N+1)%z
ENDDO
SurfaceTmp(SurfNum)%Sides=SurfaceTmp(SurfNum)%Sides-1
ELSE
IF (DisplayExtraWarnings) THEN
CALL ShowContinueError('Cannot Drop Vertex ['//trim(RoundSigDigits(SurfaceTmp(SurfNum)%Sides))//']; '// &
'Number of Surface Sides at minimum. This surface is now a degenerate surface.')
ENDIF
TotalDegenerateSurfaces=TotalDegenerateSurfaces+1
! mark degenerate surface?
ENDIF
DistanceCheck=0.0d0
ENDIF
ENDIF
Perimeter = Perimeter+DistanceCheck
Vrt=Vrt+1
IF (Vrt > SurfaceTmp(SurfNum)%Sides) EXIT
ENDDO
SurfaceTmp(SurfNum)%Perimeter=Perimeter
CALL CreateNewellSurfaceNormalVector(SurfaceTmp(SurfNum)%Vertex,SurfaceTmp(SurfNum)%Sides, &
SurfaceTmp(SurfNum)%NewellSurfaceNormalVector)
CALL CreateNewellAreaVector(SurfaceTmp(SurfNum)%Vertex,SurfaceTmp(SurfNum)%Sides,SurfaceTmp(SurfNum)%NewellAreaVector)
! For surfaces with subsurfaces, the following two areas are turned into net areas later by
! subtracting subsurface areas
SurfaceTmp(SurfNum)%GrossArea=VecLength(SurfaceTmp(SurfNum)%NewellAreaVector)
SurfaceTmp(SurfNum)%Area=SurfaceTmp(SurfNum)%GrossArea
SurfaceTmp(SurfNum)%NetAreaShadowCalc = SurfaceTmp(SurfNum)%Area
CALL DetermineAzimuthAndTilt(SurfaceTmp(SurfNum)%Vertex,SurfaceTmp(SurfNum)%Sides,SurfWorldAz,SurfTilt, &
SurfaceTmp(SurfNum)%lcsx,SurfaceTmp(SurfNum)%lcsy,SurfaceTmp(SurfNum)%lcsz, &
SurfaceTmp(SurfNum)%GrossArea,SurfaceTmp(SurfNum)%NewellSurfaceNormalVector)
dotp=SurfaceTmp(SurfNum)%NewellSurfaceNormalVector .dot. TestVector
IF (SurfaceTmp(SurfNum)%Class == SurfaceClass_Roof .and. dotp < -0.000001d0) THEN
TiltString=RoundSigDigits(SurfTilt,1)
CALL ShowWarningError(RoutineName//'Roof/Ceiling is upside down! Tilt angle=['//TRIM(TiltString)// &
'], should be near 0,'// &
' Surface="'//TRIM(SurfaceTmp(SurfNum)%Name)// &
'", in Zone="'//TRIM(SurfaceTmp(SurfNum)%ZoneName)//'".')
CALL ShowContinueError('Automatic fix is attempted.')
CALL ReverseAndRecalculate(SurfNum,SurfaceTmp(SurfNum)%Sides,SurfWorldAz,SurfTilt)
ELSEIF (SurfaceTmp(SurfNum)%Class == SurfaceClass_Roof .and. SurfTilt > 80.0d0) THEN
TiltString=RoundSigDigits(SurfTilt,1)
CALL ShowWarningError(RoutineName//'Roof/Ceiling is not oriented correctly! Tilt angle=['//TRIM(TiltString)// &
'], should be near 0,'// &
' Surface="'//TRIM(SurfaceTmp(SurfNum)%Name)// &
'", in Zone="'//TRIM(SurfaceTmp(SurfNum)%ZoneName)//'".')
ENDIF
IF (SurfaceTmp(SurfNum)%Class == SurfaceClass_Floor .and. dotp > 0.000001d0) THEN
TiltString=RoundSigDigits(SurfTilt,1)
CALL ShowWarningError(RoutineName//'Floor is upside down! Tilt angle=['//TRIM(TiltString)// &
'], should be near 180,'// &
' Surface="'//TRIM(SurfaceTmp(SurfNum)%Name)// &
'", in Zone="'//TRIM(SurfaceTmp(SurfNum)%ZoneName)//'".')
CALL ShowContinueError('Automatic fix is attempted.')
CALL ReverseAndRecalculate(SurfNum,SurfaceTmp(SurfNum)%Sides,SurfWorldAz,SurfTilt)
ELSEIF (SurfaceTmp(SurfNum)%Class == SurfaceClass_Floor .and. SurfTilt < 158.2d0) THEN ! slope/grade = 40%!
TiltString=RoundSigDigits(SurfTilt,1)
CALL ShowWarningError(RoutineName//'Floor is not oriented correctly! Tilt angle=['//TRIM(TiltString)// &
'], should be near 180,'// &
' Surface="'//TRIM(SurfaceTmp(SurfNum)%Name)// &
'", in Zone="'//TRIM(SurfaceTmp(SurfNum)%ZoneName)//'".')
ENDIF
SurfaceTmp(SurfNum)%Azimuth=SurfWorldAz
SurfaceTmp(SurfNum)%Tilt=SurfTilt
! Sine and cosine of azimuth and tilt
SurfaceTmp(SurfNum)%SinAzim = SIN(SurfWorldAz*DegToRadians)
SurfaceTmp(SurfNum)%CosAzim = COS(SurfWorldAz*DegToRadians)
SurfaceTmp(SurfNum)%SinTilt = SIN(SurfTilt*DegToRadians)
SurfaceTmp(SurfNum)%CosTilt = COS(SurfTilt*DegToRadians)
IF (SurfaceTmp(SurfNum)%ViewFactorGround == AutoCalculate) THEN
SurfaceTmp(SurfNum)%ViewFactorGround = 0.5d0 * (1.0d0 - SurfaceTmp(SurfNum)%CosTilt)
ENDIF
! Outward normal unit vector (pointing away from room)
SurfaceTmp(SurfNum)%OutNormVec = SurfaceTmp(SurfNum)%NewellSurfaceNormalVector
DO N=1,3
IF (ABS(SurfaceTmp(SurfNum)%OutNormVec(N)-1.0d0) < 1.d-06) SurfaceTmp(SurfNum)%OutNormVec(N) = +1.0d0
IF (ABS(SurfaceTmp(SurfNum)%OutNormVec(N)+1.0d0) < 1.d-06) SurfaceTmp(SurfNum)%OutNormVec(N) = -1.0d0
IF (ABS(SurfaceTmp(SurfNum)%OutNormVec(N)) < 1.d-06) SurfaceTmp(SurfNum)%OutNormVec(N) = 0.0d0
ENDDO
IF (SurfaceTmp(SurfNum)%Class == SurfaceClass_Window .or. SurfaceTmp(SurfNum)%Class == SurfaceClass_GlassDoor .or. &
SurfaceTmp(SurfNum)%Class == SurfaceClass_Door) &
SurfaceTmp(SurfNum)%Area = SurfaceTmp(SurfNum)%Area * SurfaceTmp(SurfNum)%Multiplier
! Can perform tests on this surface here
SurfaceTmp(SurfNum)%ViewFactorSky=0.5d0*(1.d0+SurfaceTmp(SurfNum)%CosTilt)
! The following IR view factors are modified in subr. SkyDifSolarShading if there are shadowing
! surfaces
SurfaceTmp(SurfNum)%ViewFactorSkyIR = SurfaceTmp(SurfNum)%ViewFactorSky
SurfaceTmp(SurfNum)%ViewFactorGroundIR = 0.5d0*(1.d0-SurfaceTmp(SurfNum)%CosTilt)
! Call to transform vertices
Call TransformVertsByAspect(SurfNum,SurfaceTmp(SurfNum)%Sides)
ELSE
CALL ShowFatalError(RoutineName//'Called with less than 2 sides, Surface='//TRIM(SurfaceTmp(SurfNum)%Name))
ENDIF
! Preliminary Height/Width
temp=SurfaceTmp(SurfNum)%Vertex(3)-SurfaceTmp(SurfNum)%Vertex(2)
ThisWidth=VecLength(temp)
temp=SurfaceTmp(SurfNum)%Vertex(2)-SurfaceTmp(SurfNum)%Vertex(1)
ThisHeight=VecLength(temp)
SurfaceTmp(SurfNum)%Height=ThisHeight
SurfaceTmp(SurfNum)%Width=ThisWidth
RETURN
END SUBROUTINE GetVertices