SurfaceGeometry.f90 Source File

This File Depends On

sourcefile~~surfacegeometry.f90~~EfferentGraph sourcefile~surfacegeometry.f90 SurfaceGeometry.f90 sourcefile~schedulemanager.f90 ScheduleManager.f90 sourcefile~schedulemanager.f90->sourcefile~surfacegeometry.f90 sourcefile~vectorutilities.f90 VectorUtilities.f90 sourcefile~vectorutilities.f90->sourcefile~surfacegeometry.f90 sourcefile~general.f90 General.f90 sourcefile~general.f90->sourcefile~surfacegeometry.f90 sourcefile~general.f90->sourcefile~schedulemanager.f90 sourcefile~general.f90->sourcefile~vectorutilities.f90 sourcefile~dataenvironment.f90 DataEnvironment.f90 sourcefile~general.f90->sourcefile~dataenvironment.f90 sourcefile~dataheatbalance.f90 DataHeatBalance.f90 sourcefile~general.f90->sourcefile~dataheatbalance.f90 sourcefile~datasurfaces.f90 DataSurfaces.f90 sourcefile~datasurfaces.f90->sourcefile~surfacegeometry.f90 sourcefile~datasurfaces.f90->sourcefile~vectorutilities.f90 sourcefile~datasurfaces.f90->sourcefile~general.f90 sourcefile~datasurfaces.f90->sourcefile~dataheatbalance.f90 sourcefile~datareportingflags.f90 DataReportingFlags.f90 sourcefile~datareportingflags.f90->sourcefile~surfacegeometry.f90 sourcefile~dataerrortracking.f90 DataErrorTracking.f90 sourcefile~dataerrortracking.f90->sourcefile~surfacegeometry.f90 sourcefile~dataheatbalsurface.f90 DataHeatBalSurface.f90 sourcefile~dataheatbalsurface.f90->sourcefile~surfacegeometry.f90 sourcefile~dataprecisionglobals.f90 DataPrecisionGlobals.f90 sourcefile~dataprecisionglobals.f90->sourcefile~surfacegeometry.f90 sourcefile~dataprecisionglobals.f90->sourcefile~schedulemanager.f90 sourcefile~dataprecisionglobals.f90->sourcefile~vectorutilities.f90 sourcefile~dataprecisionglobals.f90->sourcefile~general.f90 sourcefile~dataprecisionglobals.f90->sourcefile~datasurfaces.f90 sourcefile~dataprecisionglobals.f90->sourcefile~dataerrortracking.f90 sourcefile~dataprecisionglobals.f90->sourcefile~dataheatbalsurface.f90 sourcefile~dataglobals.f90 DataGlobals.f90 sourcefile~dataprecisionglobals.f90->sourcefile~dataglobals.f90 sourcefile~datavectortypes.f90 DataVectorTypes.f90 sourcefile~dataprecisionglobals.f90->sourcefile~datavectortypes.f90 sourcefile~dataipshortcuts.f90 DataIPShortCuts.f90 sourcefile~dataprecisionglobals.f90->sourcefile~dataipshortcuts.f90 sourcefile~dataprecisionglobals.f90->sourcefile~dataenvironment.f90 sourcefile~outputreportpredefined.f90 OutputReportPredefined.f90 sourcefile~dataprecisionglobals.f90->sourcefile~outputreportpredefined.f90 sourcefile~dataprecisionglobals.f90->sourcefile~dataheatbalance.f90 sourcefile~inputprocessor.f90 InputProcessor.f90 sourcefile~dataprecisionglobals.f90->sourcefile~inputprocessor.f90 sourcefile~datainterfaces.f90 DataInterfaces.f90 sourcefile~dataprecisionglobals.f90->sourcefile~datainterfaces.f90 sourcefile~dataequivalentlayerwindow.f90 DataEquivalentLayerWindow.f90 sourcefile~dataprecisionglobals.f90->sourcefile~dataequivalentlayerwindow.f90 sourcefile~datasystemvariables.f90 DataSystemVariables.f90 sourcefile~dataprecisionglobals.f90->sourcefile~datasystemvariables.f90 sourcefile~datahvacglobals.f90 DataHVACGlobals.f90 sourcefile~dataprecisionglobals.f90->sourcefile~datahvacglobals.f90 sourcefile~dataruntimelanguage.f90 DataRuntimeLanguage.f90 sourcefile~dataprecisionglobals.f90->sourcefile~dataruntimelanguage.f90 sourcefile~databsdfwindow.f90 DataBSDFWindow.f90 sourcefile~dataprecisionglobals.f90->sourcefile~databsdfwindow.f90 sourcefile~datacomplexfenestration.f90 DataComplexFenestration.f90 sourcefile~dataprecisionglobals.f90->sourcefile~datacomplexfenestration.f90 sourcefile~datasizing.f90 DataSizing.f90 sourcefile~dataprecisionglobals.f90->sourcefile~datasizing.f90 sourcefile~dataglobals.f90->sourcefile~surfacegeometry.f90 sourcefile~dataglobals.f90->sourcefile~schedulemanager.f90 sourcefile~dataglobals.f90->sourcefile~vectorutilities.f90 sourcefile~dataglobals.f90->sourcefile~general.f90 sourcefile~dataglobals.f90->sourcefile~datasurfaces.f90 sourcefile~dataglobals.f90->sourcefile~dataipshortcuts.f90 sourcefile~dataglobals.f90->sourcefile~dataenvironment.f90 sourcefile~dataglobals.f90->sourcefile~outputreportpredefined.f90 sourcefile~dataglobals.f90->sourcefile~dataheatbalance.f90 sourcefile~dataglobals.f90->sourcefile~inputprocessor.f90 sourcefile~dataglobals.f90->sourcefile~dataequivalentlayerwindow.f90 sourcefile~dataglobals.f90->sourcefile~datahvacglobals.f90 sourcefile~dataglobals.f90->sourcefile~dataruntimelanguage.f90 sourcefile~dataglobals.f90->sourcefile~databsdfwindow.f90 sourcefile~dataglobals.f90->sourcefile~datacomplexfenestration.f90 sourcefile~sortandstringutilities.f90 SortAndStringUtilities.f90 sourcefile~dataglobals.f90->sourcefile~sortandstringutilities.f90 sourcefile~dataoutputs.f90 DataOutputs.f90 sourcefile~dataglobals.f90->sourcefile~dataoutputs.f90 sourcefile~dataglobals.f90->sourcefile~datasizing.f90 sourcefile~datavectortypes.f90->sourcefile~surfacegeometry.f90 sourcefile~datavectortypes.f90->sourcefile~vectorutilities.f90 sourcefile~datavectortypes.f90->sourcefile~datasurfaces.f90 sourcefile~datavectortypes.f90->sourcefile~dataheatbalance.f90 sourcefile~datavectortypes.f90->sourcefile~databsdfwindow.f90 sourcefile~dataipshortcuts.f90->sourcefile~surfacegeometry.f90 sourcefile~dataipshortcuts.f90->sourcefile~schedulemanager.f90 sourcefile~dataipshortcuts.f90->sourcefile~general.f90 sourcefile~dataipshortcuts.f90->sourcefile~inputprocessor.f90 sourcefile~dataenvironment.f90->sourcefile~surfacegeometry.f90 sourcefile~dataenvironment.f90->sourcefile~schedulemanager.f90 sourcefile~dataenvironment.f90->sourcefile~dataheatbalance.f90 sourcefile~outputreportpredefined.f90->sourcefile~surfacegeometry.f90 sourcefile~dataheatbalance.f90->sourcefile~surfacegeometry.f90 sourcefile~inputprocessor.f90->sourcefile~surfacegeometry.f90 sourcefile~inputprocessor.f90->sourcefile~schedulemanager.f90 sourcefile~inputprocessor.f90->sourcefile~general.f90 sourcefile~inputprocessor.f90->sourcefile~dataheatbalance.f90 sourcefile~datainterfaces.f90->sourcefile~surfacegeometry.f90 sourcefile~datainterfaces.f90->sourcefile~schedulemanager.f90 sourcefile~datainterfaces.f90->sourcefile~vectorutilities.f90 sourcefile~datainterfaces.f90->sourcefile~general.f90 sourcefile~datainterfaces.f90->sourcefile~dataenvironment.f90 sourcefile~datainterfaces.f90->sourcefile~dataheatbalance.f90 sourcefile~datainterfaces.f90->sourcefile~inputprocessor.f90 sourcefile~datainterfaces.f90->sourcefile~dataruntimelanguage.f90 sourcefile~dataequivalentlayerwindow.f90->sourcefile~surfacegeometry.f90 sourcefile~dataequivalentlayerwindow.f90->sourcefile~dataheatbalance.f90 sourcefile~datastringglobals.f90 DataStringGlobals.f90 sourcefile~datastringglobals.f90->sourcefile~schedulemanager.f90 sourcefile~datastringglobals.f90->sourcefile~general.f90 sourcefile~datastringglobals.f90->sourcefile~inputprocessor.f90 sourcefile~datastringglobals.f90->sourcefile~datasystemvariables.f90 sourcefile~datasystemvariables.f90->sourcefile~schedulemanager.f90 sourcefile~datasystemvariables.f90->sourcefile~inputprocessor.f90 sourcefile~datahvacglobals.f90->sourcefile~general.f90 sourcefile~dataruntimelanguage.f90->sourcefile~general.f90 sourcefile~databsdfwindow.f90->sourcefile~datasurfaces.f90 sourcefile~databsdfwindow.f90->sourcefile~dataheatbalance.f90 sourcefile~datacomplexfenestration.f90->sourcefile~dataheatbalance.f90 sourcefile~sortandstringutilities.f90->sourcefile~inputprocessor.f90 sourcefile~dataoutputs.f90->sourcefile~inputprocessor.f90 sourcefile~datasizing.f90->sourcefile~inputprocessor.f90
Help

Files Dependent On This One

sourcefile~~surfacegeometry.f90~~AfferentGraph sourcefile~surfacegeometry.f90 SurfaceGeometry.f90 sourcefile~heatbalancemanager.f90 HeatBalanceManager.f90 sourcefile~surfacegeometry.f90->sourcefile~heatbalancemanager.f90 sourcefile~sizingmanager.f90 SizingManager.f90 sourcefile~heatbalancemanager.f90->sourcefile~sizingmanager.f90 sourcefile~simulationmanager.f90 SimulationManager.f90 sourcefile~heatbalancemanager.f90->sourcefile~simulationmanager.f90 sourcefile~sizingmanager.f90->sourcefile~simulationmanager.f90 sourcefile~energyplus.f90 EnergyPlus.f90 sourcefile~simulationmanager.f90->sourcefile~energyplus.f90 sourcefile~utilityroutines.f90 UtilityRoutines.f90 sourcefile~simulationmanager.f90->sourcefile~utilityroutines.f90
Help

Source Code


Source Code

MODULE SurfaceGeometry

  ! Module containing the routines dealing with the Surface Geometry

  ! MODULE INFORMATION:
  !       AUTHOR         Linda Lawrie
  !       DATE WRITTEN   June 2000
  !       MODIFIED       DJS (PSU Dec 2006) to add ecoroof
  !       RE-ENGINEERED  na

  ! PURPOSE OF THIS MODULE:
  ! This module performs the functions required of the surface geometry.

  ! METHODOLOGY EMPLOYED:
  ! na

  ! REFERENCES: none

  ! OTHER NOTES: none

  ! USE STATEMENTS:
  ! Use statements for data only modules
USE DataPrecisionGlobals
USE DataGlobals
USE DataEnvironment
USE DataHeatBalance
USE DataSurfaces
USE DataInterfaces
USE DataWindowEquivalentLayer, ONLY: CFSMAXNL

  ! Use statements for access to subroutines in other modules
  ! na

IMPLICIT NONE         ! Enforce explicit typing of all variables

PRIVATE ! Everything private unless explicitly made public

  !MODULE PARAMETER DEFINITIONS
CHARACTER(len=*), PARAMETER :: Blank=' '
CHARACTER(len=*), PARAMETER, DIMENSION(3) :: BaseSurfCls =(/'WALL ','FLOOR','ROOF '/)
CHARACTER(len=*), PARAMETER, DIMENSION(6) :: SubSurfCls  =(/'WINDOW                 ',  &
                                                            'DOOR                   ',  &
                                                            'GLASSDOOR              ',&
                                                            'SHADING                ',  &
                                                            'TUBULARDAYLIGHTDOME    ',  &
                                                            'TUBULARDAYLIGHTDIFFUSER'/)
INTEGER, PARAMETER, DIMENSION(3) :: BaseSurfIDs =(/  &
           SurfaceClass_Wall,  &
           SurfaceClass_Floor, &
           SurfaceClass_Roof/)

INTEGER, PARAMETER, DIMENSION(6) :: SubSurfIDs =(/  &
           SurfaceClass_Window,     &
           SurfaceClass_Door,       &
           SurfaceClass_GlassDoor,  &
           SurfaceClass_Shading,    &
           SurfaceClass_TDD_Dome,   &
           SurfaceClass_TDD_Diffuser/)

INTEGER, PARAMETER :: UnenteredAdjacentZoneSurface=-998     ! allows users to enter one zone surface ("Zone")
                                                            ! referencing another in adjacent zone
INTEGER, PARAMETER :: UnreconciledZoneSurface=-999          ! interim value between entering surfaces ("Surface") and reconciling
                                                            ! surface names in other zones

  character(len=*), parameter :: fmt3="(A,3(1x,f18.13))"

  ! DERIVED TYPE DEFINITIONS

  !MODULE VARIABLE DECLARATIONS:
  ! Following are used only during getting vertices, so are module variables here.
REAL(r64)   :: CosBldgRelNorth =0.0d0 ! Cosine of the building rotation (relative north) (includes appendix G rotation)
REAL(r64)   :: SinBldgRelNorth =0.0d0 ! Sine of the building rotation (relative north)   (includes appendix G rotation)
REAL(r64)   :: CosBldgRotAppGonly =0.0d0 ! Cosine of the building rotation for appendix G only(relative north)
REAL(r64)   :: SinBldgRotAppGonly =0.0d0 ! Sine of the building rotation for appendix G only (relative north)
REAL(r64), ALLOCATABLE, DIMENSION(:) :: CosZoneRelNorth ! Cosine of the zone rotation (relative north)
REAL(r64), ALLOCATABLE, DIMENSION(:) :: SinZoneRelNorth ! Sine of the zone rotation (relative north)
TYPE (SurfaceData),        ALLOCATABLE, DIMENSION(:) :: SurfaceTmp  ! Allocated/Deallocated during input processing
TYPE (SurfaceData),        ALLOCATABLE, DIMENSION(:) :: SurfaceTmpSave  ! Allocated/Deallocated during input processing

LOGICAL :: NoGroundTempObjWarning=.true.  ! This will cause a warning to be issued if surfaces with "Ground"
                                          ! outside environment are used but no ground temperature object was input.
LOGICAL :: NoFCGroundTempObjWarning=.true.  ! This will cause a warning to be issued if surfaces with "GroundFCfactorMethod"
                                          ! outside environment are used but no FC ground temperatures was input.
LOGICAL :: RectSurfRefWorldCoordSystem=.false.  ! GlobalGeometryRules=World (true) or Relative (false)
INTEGER :: Warning1Count=0  ! counts of Modify Window 5/6 windows
INTEGER :: Warning2Count=0  ! counts of overriding exterior windows with Window 5/6 glazing systems
INTEGER :: Warning3Count=0  ! counts of overriding interior windows with Window 5/6 glazing systems

  !SUBROUTINE SPECIFICATIONS FOR MODULE SurfaceGeometry
PUBLIC  SetupZoneGeometry
PRIVATE AllocateModuleArrays
PRIVATE GetSurfaceData
PRIVATE GetGeometryParameters
PRIVATE GetDetShdSurfaceData
PRIVATE GetRectDetShdSurfaceData
PRIVATE GetHTSurfaceData
PRIVATE GetRectSurfaces
PRIVATE MakeRectangularVertices
PRIVATE GetHTSubSurfaceData
PRIVATE GetRectSubSurfaces
PRIVATE CheckWindowShadingControlFrameDivider
PRIVATE CheckSubSurfaceMiscellaneous
PRIVATE MakeRelativeRectangularVertices
PRIVATE GetAttShdSurfaceData
PRIVATE GetSimpleShdSurfaceData
PRIVATE GetIntMassSurfaceData
PRIVATE GetShadingSurfReflectanceData
PRIVATE GetHTSurfExtVentedCavityData
PRIVATE GetSurfaceHeatTransferAlgorithmOverrides
PRIVATE GetVertices
PRIVATE MakeMirrorSurface
PRIVATE GetWindowShadingControlData
PRIVATE GetStormWindowData
PRIVATE GetWindowGapAirflowControlData
PRIVATE GetOSCData
PRIVATE GetOSCMData
PRIVATE GetMovableInsulationData
PRIVATE CalculateZoneVolume
PRIVATE ProcessSurfaceVertices
PRIVATE CalcCoordinateTransformation
PRIVATE CreateShadedWindowConstruction
PRIVATE CreateStormWindowConstructions
PRIVATE ModifyWindow
PRIVATE TransformVertsByAspect
PRIVATE CalcSurfaceCentroid
PRIVATE SetupShadeSurfacesForSolarCalcs
PRIVATE CheckConvexity

CONTAINS

SUBROUTINE SetupZoneGeometry(ErrorsFound)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         George Walton
          !       DATE WRITTEN   September 1977
          !       MODIFIED       April 2002 (FCW): add warning for Solar Distribution
          !                      = FullInteriorExterior when window has reveal
          !                      Add fatal error when triangular window has reveal
          !                      May 2002(FCW): Allow triangular windows to have reveal (subr SHDRVL
          !                      in SolarShading). Remove above warning and fatal error.
          !       RE-ENGINEERED  November 1997 (RKS,LKL)

          ! PURPOSE OF THIS SUBROUTINE:
          ! This subroutine controls the processing of detached shadowing and
          ! zone surfaces for computing their vertices.

          ! METHODOLOGY EMPLOYED:
          ! na

          ! REFERENCES:
          ! na

          ! USE STATEMENTS:
  USE DataVectorTypes
  USE OutputReportPredefined
  USE General, ONLY: RoundSigDigits
  USE DataReportingFlags
  USE InputProcessor, ONLY: GetNumSectionsFound

  IMPLICIT NONE    ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
  LOGICAL, INTENT(INOUT) :: ErrorsFound

          ! SUBROUTINE PARAMETER DEFINITIONS:
  CHARACTER(len=*), PARAMETER :: ValFmt="(F20.2)"
  CHARACTER(len=*), PARAMETER :: fmtA="(A)"
  CHARACTER(len=*), PARAMETER :: RoutineName='SetUpZoneGeometry: '
          ! INTERFACE BLOCK SPECIFICATIONS:
          ! na

          ! DERIVED TYPE DEFINITIONS:
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
  REAL(r64)          :: AverageHeight   ! Used to keep track of average height of a surface/zone
  INTEGER            :: SurfNum         ! Surface number (DO loop counter)
  INTEGER            :: ZoneNum         ! Zone number for current surface and DO loop counter
  REAL(r64)          :: ZMax            ! Maximum Z of a surface (detailed outside coefficient calculation)
  REAL(r64)          :: ZMin            ! Minimum Z of a surface (detailed outside coefficient calculation)
  REAL(r64)          :: ZCeilAvg
  REAL(r64)          :: CeilCount
  REAL(r64)          :: ZFlrAvg
  REAL(r64)          :: FloorCount
  REAL(r64)          :: TotSurfArea
  REAL(r64)          :: Z1
  REAL(r64)          :: Z2
  CHARACTER(len=32) String1
  CHARACTER(len=32) String2
  CHARACTER(len=3) String3
  INTEGER Count    ! To count wall surfaces for ceiling height calculation
  LOGICAL, ALLOCATABLE, DIMENSION(:) :: ZoneCeilingHeightEntered
  REAL(r64), ALLOCATABLE, DIMENSION(:) :: ZoneCeilingArea
  INTEGER, SAVE :: ErrCount=0
  REAL(r64) :: NominalUwithConvCoeffs
  CHARACTER(len=32) :: cNominalU
  CHARACTER(len=32) :: cNominalUwithConvCoeffs
  LOGICAL :: isWithConvCoefValid
!  INTEGER, ALLOCATABLE, DIMENSION(:) :: ZoneSurfacesCount
!  INTEGER, ALLOCATABLE, DIMENSION(:) :: ZoneSubSurfacesCount
!  INTEGER, ALLOCATABLE, DIMENSION(:) :: ZoneShadingSurfacesCount



  LOGICAL :: nonInternalMassSurfacesPresent
  LOGICAL :: DetailedWWR


          ! FLOW:
          ! Allocations and initializations...

          ! Zones must have been "gotten" before this call
          ! The RelNorth variables are used if "relative" coordinates are input as well
          ! as setting up DaylightingCoords

  ! these include building north axis and Building Rotation for Appendix G
  CosBldgRelNorth = COS(-(BuildingAzimuth + BuildingRotationAppendixG)*DegToRadians)
  SinBldgRelNorth = SIN(-(BuildingAzimuth + BuildingRotationAppendixG)*DegToRadians)

  ! these are only for Building Rotation for Appendix G when using world coordinate system
  CosBldgRotAppGonly = COS(-BuildingRotationAppendixG*DegToRadians)
  SinBldgRotAppGonly = SIN(-BuildingRotationAppendixG*DegToRadians)

  ALLOCATE (CosZoneRelNorth(NumOfZones))
  ALLOCATE (SinZoneRelNorth(NumOfZones))

  ALLOCATE (ZoneCeilingHeightEntered(NumOfZones))
  ZoneCeilingHeightEntered=.false.
  ALLOCATE (ZoneCeilingArea(NumOfZones))
  ZoneCeilingArea=0.0d0

  DO ZoneNum = 1, NumOfZones

    CosZoneRelNorth(ZoneNum) =  COS(-Zone(ZoneNum)%RelNorth*DegToRadians)
    SinZoneRelNorth(ZoneNum) =  SIN(-Zone(ZoneNum)%RelNorth*DegToRadians)

  END DO
  CALL GetSurfaceData(ErrorsFound)

  IF (ErrorsFound) THEN
    DEALLOCATE (CosZoneRelNorth)
    DEALLOCATE (SinZoneRelNorth)
    RETURN
  ENDIF

  CALL GetWindowGapAirflowControlData(ErrorsFound)

  CALL GetStormWindowData(ErrorsFound)

  IF(.NOT.ErrorsFound .AND. TotStormWin > 0) CALL CreateStormWindowConstructions

  DEALLOCATE (CosZoneRelNorth)
  DEALLOCATE (SinZoneRelNorth)

  CALL AllocateModuleArrays ! This needs to be moved to the main manager routine of SSG at a later date

  ALLOCATE(AirSkyRadSplit(TotSurfaces))
  AirSkyRadSplit=0.0d0

  CalcWindowRevealReflection = .FALSE. ! Set to True in ProcessSurfaceVertices if beam solar reflection from window reveals
                                       ! is requested for one or more exterior windows.
  BuildingShadingCount =0
  FixedShadingCount    =0
  AttachedShadingCount =0

  DO SurfNum = 1, TotSurfaces   ! Loop through all surfaces...

    AirSkyRadSplit(SurfNum) = SQRT(0.5d0*(1.0d0+Surface(SurfNum)%CosTilt))

    ! Set flag that determines whether a surface is a shadowing surface
    Surface(SurfNum)%ShadowingSurf = .FALSE.
    IF(Surface(SurfNum)%Class == SurfaceClass_Shading .OR. Surface(SurfNum)%Class == SurfaceClass_Detached_F .OR.  &
       Surface(SurfNum)%Class == SurfaceClass_Detached_B) Surface(SurfNum)%ShadowingSurf = .TRUE.
    IF (Surface(SurfNum)%Class == SurfaceClass_Shading) AttachedShadingCount=AttachedShadingCount+1
    IF (Surface(SurfNum)%Class == SurfaceClass_Detached_F) FixedShadingCount=FixedShadingCount+1
    IF (Surface(SurfNum)%Class == SurfaceClass_Detached_B) BuildingShadingCount=BuildingShadingCount+1

    IF (Surface(SurfNum)%Class /= SurfaceClass_IntMass) CALL ProcessSurfaceVertices(SurfNum,ErrorsFound)
  END DO

  Zone%ExtWindowArea=0.0d0
  Zone%HasInterZoneWindow=.false.
  Zone%HasWindow=.false.
  Zone%ExtGrossWallArea=0.0d0
  Zone%ExtNetWallArea=0.0d0
  Zone%TotalSurfArea=0.0d0

  DetailedWWR=(GetNumSectionsFound('DETAILEDWWR_DEBUG') > 0)
  IF (DetailedWWR) THEN
    WRITE(OutputFileDebug,'(A)') '=======User Entered Classification ================='
    WRITE(OutputFileDebug,'(A)') 'Surface,Class,Area,Tilt'
  ENDIF

  DO SurfNum = 1, TotSurfaces ! Loop through all surfaces to find windows...

    IF (.NOT.Surface(SurfNum)%HeatTransSurf) CYCLE    ! Skip shadowing (sub)surfaces
    ZoneNum=Surface(SurfNum)%Zone
    Zone(ZoneNum)%TotalSurfArea = Zone(ZoneNum)%TotalSurfArea + Surface(SurfNum)%Area
    IF(Construct(Surface(SurfNum)%Construction)%TypeIsWindow) THEN
      Zone(ZoneNum)%TotalSurfArea = Zone(ZoneNum)%TotalSurfArea + SurfaceWindow(SurfNum)%FrameArea
      Zone(ZoneNum)%HasWindow = .true.
    ENDIF
    IF (Surface(SurfNum)%Class == SurfaceClass_Roof) ZoneCeilingArea(ZoneNum)=ZoneCeilingArea(ZoneNum)+Surface(SurfNum)%Area
    IF (.NOT. Construct(Surface(SurfNum)%Construction)%TypeIsWindow) THEN
      IF (Surface(SurfNum)%ExtBoundCond == ExternalEnvironment  .or. &
          Surface(SurfNum)%ExtBoundCond == OtherSideCondModeledExt ) THEN
        Zone(ZoneNum)%ExteriorTotalSurfArea=Zone(ZoneNum)%ExteriorTotalSurfArea +   &
                           Surface(SurfNum)%GrossArea
        IF (Surface(SurfNum)%Class == SurfaceClass_Wall) THEN
          Zone(ZoneNum)%ExtNetWallArea = Zone(ZoneNum)%ExtNetWallArea +   &
                           Surface(SurfNum)%Area
          Zone(ZoneNum)%ExtGrossWallArea = Zone(ZoneNum)%ExtGrossWallArea +   &
                           Surface(SurfNum)%GrossArea
          Zone(ZoneNum)%ExtGrossWallArea_Multiplied = Zone(ZoneNum)%ExtGrossWallArea_Multiplied +   &
                           Surface(SurfNum)%GrossArea * Zone(ZoneNum)%Multiplier * Zone(ZoneNum)%ListMultiplier
          IF (DetailedWWR) THEN
            WRITE(OutputFileDebug,'(A)') trim(Surface(SurfNum)%Name)//',Wall,'//  &
               trim(RoundSigDigits(Surface(SurfNum)%GrossArea*Zone(ZoneNum)%Multiplier*Zone(ZoneNum)%ListMultiplier,2))//  &
               ','//trim(RoundSigDigits(Surface(SurfNum)%Tilt,1))
          ENDIF
        ENDIF
      ELSEIF (Surface(SurfNum)%ExtBoundCond == Ground .or. Surface(SurfNum)%ExtBoundCond == GroundFCfactorMethod) THEN
        Zone(ZoneNum)%ExteriorTotalGroundSurfArea=Zone(ZoneNum)%ExteriorTotalGroundSurfArea +   &
                           Surface(SurfNum)%GrossArea
        IF (Surface(SurfNum)%Class == SurfaceClass_Wall) THEN
          Zone(ZoneNum)%ExtGrossGroundWallArea = Zone(ZoneNum)%ExtGrossGroundWallArea +   &
                           Surface(SurfNum)%GrossArea
          Zone(ZoneNum)%ExtGrossGroundWallArea_Multiplied = Zone(ZoneNum)%ExtGrossGroundWallArea_Multiplied +   &
                           Surface(SurfNum)%GrossArea * Zone(ZoneNum)%Multiplier * Zone(ZoneNum)%ListMultiplier
          IF (DetailedWWR) THEN
            WRITE(OutputFileDebug,'(A)') trim(Surface(SurfNum)%Name)//',Wall-GroundContact,'//  &
               trim(RoundSigDigits(Surface(SurfNum)%GrossArea*Zone(ZoneNum)%Multiplier*Zone(ZoneNum)%ListMultiplier,2))//  &
               ','//trim(RoundSigDigits(Surface(SurfNum)%Tilt,1))
          ENDIF
        ENDIF
      ENDIF

    ELSE  ! For Windows

      IF ((Surface(SurfNum)%ExtBoundCond > 0) .AND. (Surface(SurfNum)%BaseSurf /= SurfNum)) THEN ! Interzone window present
        IF (.not. IgnoreInteriorWindowTransmission) THEN
          Zone(Surface(SurfNum)%Zone)%HasInterZoneWindow=.TRUE.
        ENDIF
      ELSE
        IF (( (Surface(SurfNum)%ExtBoundCond == ExternalEnvironment) .OR.   &
                (Surface(SurfNum)%ExtBoundCond == OtherSideCondModeledExt) )&
             .AND. (Surface(SurfNum)%Class .NE. SurfaceClass_TDD_Dome)) THEN
          Zone(Surface(SurfNum)%Zone)%ExtWindowArea = Zone(Surface(SurfNum)%Zone)%ExtWindowArea + Surface(SurfNum)%GrossArea
          Zone(Surface(SurfNum)%Zone)%ExtWindowArea_Multiplied = Zone(Surface(SurfNum)%Zone)%ExtWindowArea +   &
             Surface(SurfNum)%GrossArea*Surface(SurfNum)%Multiplier*Zone(ZoneNum)%Multiplier*Zone(ZoneNum)%ListMultiplier
          IF (DetailedWWR) THEN
            WRITE(OutputFileDebug,'(A)') trim(Surface(SurfNum)%Name)//',Window,'//  &
               trim(RoundSigDigits(Surface(SurfNum)%GrossArea*Surface(SurfNum)%Multiplier*  &
                                   Zone(ZoneNum)%Multiplier*Zone(ZoneNum)%ListMultiplier,2))//  &
                    ','//trim(RoundSigDigits(Surface(SurfNum)%Tilt,1))
          ENDIF
       ENDIF
      ENDIF

    ENDIF

  END DO    ! ...end of surfaces windows DO loop

!  DO SurfNum = 1, TotSurfaces ! Set areas for Sunlit area calculations for Windows
!    IF (Surface(SurfNum)%Class /= SurfaceClass_Window) CYCLE
!    SurfaceWindow(SurfNum)%AreaCalcForSunlitArea = (Surface(SurfNum)%Area + SurfaceWindow(SurfNum)%DividerArea) /  &
!                                  Surface(SurfNum)%Multiplier
!  ENDDO
  IF (DetailedWWR) THEN
    WRITE(OutputFileDebug,'(A)') '========================'
    WRITE(OutputFileDebug,'(A)') 'Zone,ExtWallArea,ExtWindowArea'
  ENDIF

  DO ZoneNum = 1, NumOfZones
    CeilCount=0.0d0
    FloorCount=0.0d0
    Count=0
    AverageHeight=0.0d0
    ZCeilAvg=0.0d0
    ZFlrAvg=0.0d0
    ZMax=-99999.0d0
    ZMin=99999.0d0
    IF (DetailedWWR) THEN
      WRITE(OutputFileDebug,'(A)') trim(Zone(ZoneNum)%Name)//','//  &
               trim(RoundSigDigits(Zone(ZoneNum)%ExtGrossWallArea,2))//','//  &
               trim(RoundSigDigits(Zone(ZoneNum)%ExtWindowArea,2))
    ENDIF
    DO SurfNum=Zone(ZoneNum)%SurfaceFirst,Zone(ZoneNum)%SurfaceLast
      IF (Surface(SurfNum)%Class == SurfaceClass_Roof) THEN
        ! Use Average Z for surface, more important for roofs than floors...
        CeilCount=CeilCount+1.0d0
        Z1=MINVAL(Surface(SurfNum)%Vertex(1:Surface(SurfNum)%Sides)%Z)
        Z2=MAXVAL(Surface(SurfNum)%Vertex(1:Surface(SurfNum)%Sides)%Z)
!        ZCeilAvg=ZCeilAvg+(Z1+Z2)/2.d0
        ZCeilAvg=ZCeilAvg+((Z1+Z2)/2.d0)*(Surface(SurfNum)%Area/ZoneCeilingArea(ZoneNum))
      ENDIF
      IF (Surface(SurfNum)%Class == SurfaceClass_Floor) THEN
        ! Use Average Z for surface, more important for roofs than floors...
        FloorCount=FloorCount+1.0d0
        Z1=MINVAL(Surface(SurfNum)%Vertex(1:Surface(SurfNum)%Sides)%Z)
        Z2=MAXVAL(Surface(SurfNum)%Vertex(1:Surface(SurfNum)%Sides)%Z)
!        ZFlrAvg=ZFlrAvg+(Z1+Z2)/2.d0
        ZFlrAvg=ZFlrAvg+((Z1+Z2)/2.d0)*(Surface(SurfNum)%Area/Zone(ZoneNum)%FloorArea)
      ENDIF
      IF (Surface(SurfNum)%Class == SurfaceClass_Wall) THEN
        ! Use Wall calculation in case no roof & floor in zone
        Count=Count+1
        IF (Count == 1) THEN
          ZMax=Surface(SurfNum)%Vertex(1)%Z
          ZMin=ZMax
        ENDIF
        ZMax=MAX(ZMax,MAXVAL(Surface(SurfNum)%Vertex(1:Surface(SurfNum)%Sides)%Z))
        ZMin=MIN(ZMin,MINVAL(Surface(SurfNum)%Vertex(1:Surface(SurfNum)%Sides)%Z))
      ENDIF
    ENDDO
    IF (CeilCount > 0.0d0 .and. FloorCount > 0.0d0) THEN
!      ZCeilAvg=ZCeilAvg/CeilCount
!      ZFlrAvg=ZFlrAvg/FloorCount
      AverageHeight=ZCeilAvg-ZFlrAvg
    ELSE
      AverageHeight=(ZMax-ZMin)
    ENDIF
    IF (AverageHeight <= 0.0d0) THEN
      AverageHeight=(ZMax-ZMin)
    ENDIF

    IF (Zone(ZoneNum)%CeilingHeight > 0.0d0) THEN
      ZoneCeilingHeightEntered(ZoneNum)=.true.
      IF (AverageHeight > 0.0d0) THEN
        IF (ABS(AverageHeight-Zone(ZoneNum)%CeilingHeight)/Zone(ZoneNum)%CeilingHeight  > .05d0) THEN
          IF (ErrCount == 1 .and. .not. DisplayExtraWarnings) THEN
            CALL ShowWarningError(RoutineName//'Entered Ceiling Height for some zone(s) significantly '//  &
               'different from calculated Ceiling Height')
            CALL ShowContinueError('...use Output:Diagnostics,DisplayExtraWarnings; '// &
                 'to show more details on each max iteration exceeded.')
          ENDIF
          IF (DisplayExtraWarnings) THEN
            CALL ShowWarningError(RoutineName//'Entered Ceiling Height for Zone="'//TRIM(Zone(ZoneNum)%Name)//  &
                                  '" significantly different from calculated Ceiling Height')
            WRITE(String1,ValFmt) Zone(ZoneNum)%CeilingHeight
            String1=ADJUSTL(String1)
            WRITE(String2,ValFmt) AverageHeight
            String2=ADJUSTL(String2)
            CALL ShowContinueError(RoutineName//'Entered Ceiling Height='//TRIM(String1)//  &
               ', Calculated Ceiling Height='//TRIM(String2)// &
               ', entered height will be used in calculations.')
          ENDIF
        ENDIF
      ENDIF
    ENDIF
    IF ((Zone(ZoneNum)%CeilingHeight <= 0.0d0).AND.(AverageHeight > 0.0d0)) &
         Zone(ZoneNum)%CeilingHeight = AverageHeight

  END DO

  CALL CalculateZoneVolume(ErrorsFound,ZoneCeilingHeightEntered)    ! Calculate Zone Volumes

  ! Calculate zone centroid (and min/max x,y,z for zone)
  DO ZoneNum = 1, NumOfZones
    nonInternalMassSurfacesPresent=.false.
    TotSurfArea = 0.0d0
    Zone(ZoneNum)%Centroid = Vector(0.0d0, 0.0d0, 0.0d0)
    IF (Surface(Zone(ZoneNum)%SurfaceFirst)%Sides > 0) THEN
      Zone(ZoneNum)%MinimumX=Surface(Zone(ZoneNum)%SurfaceFirst)%Vertex(1)%x
      Zone(ZoneNum)%MaximumX=Surface(Zone(ZoneNum)%SurfaceFirst)%Vertex(1)%x
      Zone(ZoneNum)%MinimumY=Surface(Zone(ZoneNum)%SurfaceFirst)%Vertex(1)%y
      Zone(ZoneNum)%MaximumY=Surface(Zone(ZoneNum)%SurfaceFirst)%Vertex(1)%y
      Zone(ZoneNum)%MinimumZ=Surface(Zone(ZoneNum)%SurfaceFirst)%Vertex(1)%z
      Zone(ZoneNum)%MaximumZ=Surface(Zone(ZoneNum)%SurfaceFirst)%Vertex(1)%z
    ENDIF
    DO SurfNum = Zone(ZoneNum)%SurfaceFirst, Zone(ZoneNum)%SurfaceLast
      IF (Surface(SurfNum)%Class == SurfaceClass_IntMass) CYCLE
      nonInternalMassSurfacesPresent=.true.
      IF (Surface(SurfNum)%Class == SurfaceClass_Wall  &
        .OR. (Surface(SurfNum)%Class == SurfaceClass_Roof) &
        .OR. (Surface(SurfNum)%Class == SurfaceClass_Floor)) THEN

        Zone(ZoneNum)%Centroid%x = Zone(ZoneNum)%Centroid%x + Surface(SurfNum)%Centroid%x * Surface(SurfNum)%GrossArea
        Zone(ZoneNum)%Centroid%y = Zone(ZoneNum)%Centroid%y + Surface(SurfNum)%Centroid%y * Surface(SurfNum)%GrossArea
        Zone(ZoneNum)%Centroid%z = Zone(ZoneNum)%Centroid%z + Surface(SurfNum)%Centroid%z * Surface(SurfNum)%GrossArea
        TotSurfArea = TotSurfArea + Surface(SurfNum)%GrossArea
      END IF
      Zone(ZoneNum)%MinimumX=MIN(Zone(ZoneNum)%MinimumX,MINVAL(Surface(SurfNum)%Vertex(1:Surface(SurfNum)%Sides)%x))
      Zone(ZoneNum)%MaximumX=MAX(Zone(ZoneNum)%MaximumX,MAXVAL(Surface(SurfNum)%Vertex(1:Surface(SurfNum)%Sides)%x))
      Zone(ZoneNum)%MinimumY=MIN(Zone(ZoneNum)%MinimumY,MINVAL(Surface(SurfNum)%Vertex(1:Surface(SurfNum)%Sides)%y))
      Zone(ZoneNum)%MaximumY=MAX(Zone(ZoneNum)%MaximumY,MAXVAL(Surface(SurfNum)%Vertex(1:Surface(SurfNum)%Sides)%y))
      Zone(ZoneNum)%MinimumZ=MIN(Zone(ZoneNum)%MinimumZ,MINVAL(Surface(SurfNum)%Vertex(1:Surface(SurfNum)%Sides)%z))
      Zone(ZoneNum)%MaximumZ=MAX(Zone(ZoneNum)%MaximumZ,MAXVAL(Surface(SurfNum)%Vertex(1:Surface(SurfNum)%Sides)%z))
    END DO
    IF (TotSurfArea > 0.0d0) THEN
      Zone(ZoneNum)%Centroid%x = Zone(ZoneNum)%Centroid%x / TotSurfArea
      Zone(ZoneNum)%Centroid%y = Zone(ZoneNum)%Centroid%y / TotSurfArea
      Zone(ZoneNum)%Centroid%z = Zone(ZoneNum)%Centroid%z / TotSurfArea
    ENDIF
    IF (.not. nonInternalMassSurfacesPresent) THEN
      CALL ShowSevereError(RoutineName//'Zone="'//trim(Zone(ZoneNum)%Name)//  &
             '" has only internal mass surfaces.  Need at least one other surface.')
      ErrorsFound=.true.
    ENDIF
  END DO

  DEALLOCATE(ZoneCeilingHeightEntered)
  DEALLOCATE(ZoneCeilingArea)

  ALLOCATE(AdjacentZoneToSurface(TotSurfaces))
  AdjacentZoneToSurface=0
  ! note -- adiabatic surfaces will show same zone as surface
  do surfnum=1,totsurfaces
    if (Surface(surfnum)%ExtBoundCond <= 0) CYCLE
    AdjacentZoneToSurface(surfnum)=Surface(Surface(surfNum)%ExtBoundCond)%Zone
  enddo

  do zonenum=1,NumOfZones
    do surfnum=1,totsurfaces
      if (.not. Surface(surfnum)%HeatTransSurf .and. Surface(surfnum)%ZoneName == Zone(zonenum)%Name) &
        Zone(zonenum)%NumShadingSurfaces=Zone(zonenum)%NumShadingSurfaces+1

      if (Surface(surfnum)%Zone /= zonenum) CYCLE

      if (Surface(surfnum)%HeatTransSurf .and. (Surface(surfnum)%class == SurfaceClass_Wall .or.          &
          Surface(surfnum)%class == SurfaceClass_Roof .or. Surface(surfnum)%class == SurfaceClass_Floor)) &
        Zone(zonenum)%NumSurfaces=Zone(zonenum)%NumSurfaces+1

      if (Surface(surfnum)%HeatTransSurf .and. (Surface(surfnum)%class == SurfaceClass_Window .or.                   &
          Surface(surfnum)%class == SurfaceClass_GlassDoor .or. Surface(surfnum)%class == SurfaceClass_Door .or.     &
          Surface(surfnum)%class == SurfaceClass_TDD_Dome .or. Surface(surfnum)%class == SurfaceClass_TDD_Diffuser)) &
        Zone(zonenum)%NumSubSurfaces=Zone(zonenum)%NumSubSurfaces+1

    enddo  ! surfaces
  enddo ! zones

  do surfnum=1,totsurfaces
    if (Surface(surfnum)%Construction > 0 .and. Surface(surfnum)%Construction <= TotConstructs) THEN
      NominalUwithConvCoeffs = ComputeNominalUwithConvCoeffs(surfnum,isWithConvCoefValid)
      IF (isWithConvCoefValid) THEN
        cNominalUwithConvCoeffs=RoundSigDigits(NominalUwithConvCoeffs,3)
      ELSE
        cNominalUwithConvCoeffs = '[invalid]'
      END IF
      IF ((Surface(surfnum)%class == SurfaceClass_Window) .OR. (Surface(surfnum)%class == SurfaceClass_TDD_Dome)) THEN
        ! SurfaceClass_Window also covers glass doors and TDD:Diffusers
        cNominalU='N/A'
      ELSE
        cNominalU=RoundSigDigits(NominalU(Surface(surfnum)%Construction),3)
      END IF
    else
      CNominalUwithConvCoeffs = '**'
      CNominalU = '**'
    endif

    ! save the U-value nominal for use later in tabular report
    Surface(surfnum)%UNomWOFilm = cNominalU
    Surface(surfnum)%UNomFilm = cNominalUwithConvCoeffs
    !populate the predefined report related to u-values with films
    !only exterior surfaces including underground
    IF ((Surface(surfnum)%ExtBoundCond .EQ. ExternalEnvironment) .OR. (Surface(surfnum)%ExtBoundCond .EQ. Ground)) THEN
      SELECT CASE (Surface(surfnum)%Class)
        CASE (SurfaceClass_Wall,SurfaceClass_Floor,SurfaceClass_Roof)
          CALL PreDefTableEntry(pdchOpUfactFilm,Surface(surfnum)%Name,NominalUwithConvCoeffs,3)
        CASE (SurfaceClass_Door)
          CALL PreDefTableEntry(pdchDrUfactFilm,Surface(surfnum)%Name,NominalUwithConvCoeffs,3)
      END SELECT
    END IF
  enddo  ! surfaces

  ! Write number of shadings to initialization output file
  WRITE(OutputFileInits,fmtA) '! <Shading Summary>, Number of Fixed Detached Shades, Number of Building Detached Shades, '//  &
     'Number of Attached Shades'

  WRITE(OutputFileInits,fmtA) ' Shading Summary,'//TRIM(RoundSigDigits(FixedShadingCount))//','//  &
     trim(RoundSigDigits(BuildingShadingCount))//','//  &
     trim(RoundSigDigits(AttachedShadingCount))

  ! Write number of zones header to initialization output file
  WRITE(OutputFileInits,fmtA) '! <Zone Summary>, Number of Zones, Number of Zone Surfaces, Number of SubSurfaces'

  WRITE(OutputFileInits,fmtA) ' Zone Summary,'//TRIM(RoundSigDigits(NumOfZones))//','//  &
     trim(RoundSigDigits(TotSurfaces-FixedShadingCount-BuildingShadingCount-AttachedShadingCount))//','//  &
     trim(RoundSigDigits(SUM(Zone%NumSubSurfaces)))

  ! Write Zone Information header to the initialization output file
  WRITE(OutputFileInits,721)

  DO ZoneNum=1,NumOfZones
    ! Write Zone Information to the initialization output file

    SELECT CASE (Zone(ZoneNum)%InsideConvectionAlgo)
      CASE (ASHRAESimple)
        String1='Simple'
      CASE (ASHRAETARP)
        String1='TARP'
      CASE (CeilingDiffuser)
        String1='CeilingDiffuser'
      CASE (TrombeWall)
        String1='TrombeWall'
      CASE (AdaptiveConvectionAlgorithm)
        String1='AdaptiveConvectionAlgorithm'
    END SELECT

    SELECT CASE (Zone(ZoneNum)%OutsideConvectionAlgo)
      CASE (ASHRAESimple)
        String2='Simple'
      CASE (ASHRAETARP)
        String2='TARP'
      CASE (TarpHcOutside)
        String2='TARP'
      CASE (MoWittHcOutside)
        String2='MoWitt'
      CASE (DOE2HcOutside)
        String2='DOE-2'
!      CASE (BLASTHcOutside)
!        String2='BLAST'
      CASE (AdaptiveConvectionAlgorithm)
        String2='AdaptiveConvectionAlgorithm'

    END SELECT

    IF (Zone(ZoneNum)%isPartOfTotalArea) THEN
      String3='Yes'
    ELSE
      String3='No'
    ENDIF

    WRITE(OutputFileInits,720) TRIM(Zone(ZoneNum)%Name),TRIM(RoundSigDigits(Zone(ZoneNum)%RelNorth,1)),                         &
                             TRIM(RoundSigDigits(Zone(ZoneNum)%OriginX,2)),TRIM(RoundSigDigits(Zone(ZoneNum)%OriginY,2)),       &
                             TRIM(RoundSigDigits(Zone(ZoneNum)%OriginZ,2)),TRIM(RoundSigDigits(Zone(ZoneNum)%Centroid%X,2)),    &
                             TRIM(RoundSigDigits(Zone(ZoneNum)%Centroid%Y,2)),TRIM(RoundSigDigits(Zone(ZoneNum)%Centroid%Z,2)), &
                             TRIM(RoundSigDigits(Zone(ZoneNum)%OfType)),                                                &
                             TRIM(RoundSigDigits(Zone(ZoneNum)%Multiplier)),                                            &
                             TRIM(RoundSigDigits(Zone(ZoneNum)%ListMultiplier)),                                        &
                             TRIM(RoundSigDigits(Zone(ZoneNum)%MinimumX,2)),TRIM(RoundSigDigits(Zone(ZoneNum)%MaximumX,2)),     &
                             TRIM(RoundSigDigits(Zone(ZoneNum)%MinimumY,2)),TRIM(RoundSigDigits(Zone(ZoneNum)%MaximumY,2)),     &
                             TRIM(RoundSigDigits(Zone(ZoneNum)%MinimumZ,2)),TRIM(RoundSigDigits(Zone(ZoneNum)%MaximumZ,2)),     &
                             TRIM(RoundSigDigits(Zone(ZoneNum)%CeilingHeight,2)),TRIM(RoundSigDigits(Zone(ZoneNum)%Volume,2)),  &
                             TRIM(String1),TRIM(String2),TRIM(RoundSigDigits(Zone(ZoneNum)%FloorArea,2)),                       &
                             TRIM(RoundSigDigits(Zone(ZoneNum)%ExtGrossWallArea,2)),                                            &
                             TRIM(RoundSigDigits(Zone(ZoneNum)%ExtNetWallArea,2)),                                              &
                             TRIM(RoundSigDigits(Zone(ZoneNum)%ExtWindowArea,2)),                                               &
                             TRIM(RoundSigDigits(Zone(ZoneNum)%NumSurfaces)),                                                  &
                             TRIM(RoundSigDigits(Zone(ZoneNum)%NumSubSurfaces)),                                               &
                             TRIM(RoundSigDigits(Zone(ZoneNum)%NumShadingSurfaces)),                                           &
                             TRIM(String3)

  END DO ! ZoneNum

! Do the Stratosphere check
  CALL SetOutBulbTempAt(NumOfZones, Zone(1:NumOfZones)%Centroid%Z,           &
       Zone(1:NumOfZones)%OutDryBulbTemp, Zone(1:NumOfZones)%OutWetBulbTemp, 'Zone')

!  IF (ALLOCATED(ZoneSurfacesCount)) DEALLOCATE(ZoneSurfacesCount)
!  IF (ALLOCATED(ZoneSubSurfacesCount)) DEALLOCATE(ZoneSubSurfacesCount)
!  IF (ALLOCATED(ZoneShadingSurfacesCount)) DEALLOCATE(ZoneShadingSurfacesCount)

720 FORMAT(' Zone Information, ',A,28(',',A))
721 FORMAT('! <Zone Information>,Zone Name,North Axis {deg},', &
           'Origin X-Coordinate {m},Origin Y-Coordinate {m},Origin Z-Coordinate {m},', &
           'Centroid X-Coordinate {m},Centroid Y-Coordinate {m},Centroid Z-Coordinate {m},', &
           'Type,Zone Multiplier,Zone List Multiplier,Minimum X {m},Maximum X {m},',         &
           'Minimum Y {m},Maximum Y {m},Minimum Z {m},Maximum Z {m},Ceiling Height {m},Volume {m3},', &
           'Zone Inside Convection Algorithm {Simple-Detailed-CeilingDiffuser-TrombeWall},', &
           'Zone Outside Convection Algorithm {Simple-Detailed-Tarp-MoWitt-DOE-2-BLAST},', &
          ' Floor Area {m2},Exterior Gross Wall Area {m2},Exterior Net Wall Area {m2},Exterior Window Area {m2},', &
          ' Number of Surfaces, Number of SubSurfaces, Number of Shading SubSurfaces, ',  &
          ' Part of Total Building Area')

  RETURN

END SUBROUTINE SetUpZoneGeometry

SUBROUTINE AllocateModuleArrays

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Rick Strand
          !       DATE WRITTEN   February 1998
          !       MODIFIED       na
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! This subroutine allocates all of the arrays at the module level which
          ! require allocation.

          ! METHODOLOGY EMPLOYED:
          ! Allocation is dependent on the user input file.

          ! REFERENCES:
          ! na

          ! USE STATEMENTS:
          ! na

  IMPLICIT NONE    ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE PARAMETER DEFINITIONS:
          ! na

          ! INTERFACE BLOCK SPECIFICATIONS
          ! na

          ! DERIVED TYPE DEFINITIONS
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
          ! na

          ! FLOW:

  ALLOCATE (ShadeV(TotSurfaces))
  ShadeV%NVert=0
  ! Individual components (XV,YV,ZV) allocated in routine ProcessSurfaceVertices
  ALLOCATE (X0(TotSurfaces))
  X0=0.0d0
  ALLOCATE (Y0(TotSurfaces))
  Y0=0.0d0
  ALLOCATE (Z0(TotSurfaces))
  Z0=0.0d0

  ALLOCATE (CBZone(NumOfZones))
  CBZone=0.0d0
  ALLOCATE (DSZone(NumOfZones))
  DSZone=0.0d0
  ALLOCATE (DGZone(NumOfZones))
  DGZone=0.0d0
  ALLOCATE (DBZone(NumOfZones))
  DBZone=0.0d0
  ALLOCATE (DBZoneSSG(NumOfZones))
  DBZoneSSG = 0.0d0
  ALLOCATE (QSDifSol(NumOfZones))
  QSDifSol=0.0d0
  ALLOCATE (AISurf(TotSurfaces))
  AISurf=0.0d0
  ALLOCATE (AOSurf(TotSurfaces))
  AOSurf=0.0d0
  ALLOCATE (BmToBmReflFacObs(TotSurfaces))
  BmToBmReflFacObs=0.0d0
  ALLOCATE (BmToDiffReflFacObs(TotSurfaces))
  BmToDiffReflFacObs=0.0d0
  ALLOCATE (BmToDiffReflFacGnd(TotSurfaces))
  BmToDiffReflFacGnd=0.0d0
  ALLOCATE (AWinSurf(TotSurfaces,CFSMAXNL+1))
  AWinSurf=0.0d0
  ALLOCATE (AWinCFOverlap(TotSurfaces,MaxSolidWinLayers))
  AWinCFOverlap=0.0d0

  RETURN

END SUBROUTINE AllocateModuleArrays

SUBROUTINE GetSurfaceData(ErrorsFound)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Richard Liesen
          !       DATE WRITTEN   November 1997
          !       MODIFIED       April 1999, Linda Lawrie
          !                      Dec. 2000, FW (add "one-wall zone" checks)
          !       RE-ENGINEERED  May 2000, Linda Lawrie (breakout surface type gets)

          ! PURPOSE OF THIS SUBROUTINE:
          ! The purpose of this subroutine is to read in the surface information
          ! from the input data file and interpret and put in the derived type

          ! METHODOLOGY EMPLOYED:
          ! The order of surfaces does not matter and the surfaces are resorted into
          ! the hierarchical order:
          !  Detached Surfaces
          !  Base Surface for zone x
          !    Subsurfaces for base surface
          !  Base Surface for zone x
          !    etc
          !  Heat Transfer Surfaces and Shading surfaces are mixed in the list
          !  Pointers are set in the zones (First, Last)

          ! REFERENCES:
  !   This routine manages getting the input for the following Objects:
  ! SurfaceGeometry
  ! Surface:Shading:Detached
  ! Surface:HeatTransfer
  ! Surface:HeatTransfer:Sub
  ! Surface:Shading:Attached
  ! Surface:InternalMass

  !
  ! Vertex input:
  !  N3 , \field Number of Surface Vertices -- Number of (X,Y,Z) groups in this surface
  !       \note currently limited 3 or 4, later?
  !       \min 3
  !       \max 4
  !       \memo vertices are given in SurfaceGeometry coordinates -- if relative, all surface coordinates
  !       \memo are "relative" to the Zone Origin.  if WCS, then building and zone origins are used
  !       \memo for some internal calculations, but all coordinates are given in an "absolute" system.
  !  N4,  \field Vertex 1 X-coordinate
  !       \units m
  !       \type real
  !  N5 , \field Vertex 1 Y-coordinate
  !       \units m
  !       \type real
  !  N6 , \field Vertex 1 Z-coordinate
  !       \units m
  !       \type real
  !  N7,  \field Vertex 2 X-coordinate
  !       \units m
  !       \type real
  !  N8,  \field Vertex 2 Y-coordinate
  !       \units m
  !       \type real
  !  N9,  \field Vertex 2 Z-coordinate
  !       \units m
  !       \type real
  !  N10, \field Vertex 3 X-coordinate
  !       \units m
  !       \type real
  !  N11, \field Vertex 3 Y-coordinate
  !       \units m
  !       \type real
  !  N12, \field Vertex 3 Z-coordinate
  !       \units m
  !       \type real
  !  N13, \field Vertex 4 X-coordinate
  !       \units m
  !       \type real
  !  N14, \field Vertex 4 Y-coordinate
  !       \type real
  !       \units m
  !  N15; \field Vertex 4 Z-coordinate
  !       \units m
  !       \type real

  ! The vertices are stored in the surface derived type.
  !
  !      +(1)-------------------------(4)+
  !      |                               |
  !      |                               |
  !      |                               |
  !      +(2)-------------------------(3)+
  !
  !  The above diagram shows the actual coordinate points of a typical wall
  !  (you're on the outside looking toward the wall) as stored into
  !  Surface%Vertex(1:<number-of-sides>)
  !
  !
  !


          ! USE STATEMENTS:
  USE DataIPShortCuts
  USE InputProcessor, ONLY: GetNumObjectsFound, GetObjectItem, FindItemInList, SameString, VerifyName
  USE General, ONLY: TrimSigDigits,RoundSigDigits
  USE Vectors
  USE ScheduleManager, ONLY: GetScheduleMinValue, GetScheduleMaxValue
  USE DataErrorTracking

  IMPLICIT NONE    ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
  LOGICAL, INTENT(INOUT) :: ErrorsFound ! If errors found in input

          ! SUBROUTINE PARAMETER DEFINITIONS:
  INTEGER, PARAMETER :: SurfaceClass_Moved=-1
  CHARACTER(len=*), PARAMETER :: RoutineName='GetSurfaceData: '

          ! INTERFACE BLOCK SPECIFICATIONS
          ! na

          ! DERIVED TYPE DEFINITIONS
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:

  INTEGER :: ConstrNum         ! Construction number
  INTEGER :: SubSurfNum        ! DO loop counter/index for sub-surface number
  INTEGER :: SurfNum           ! DO loop counter/index for surface number
  INTEGER :: ZoneNum           ! DO loop counter (zones)
  INTEGER :: Found             ! For matching interzone surfaces
  INTEGER :: ConstrNumFound    ! Construction number of matching interzone surface
  LOGICAL :: NonMatch=.false.  ! Error for non-matching interzone surfaces
  INTEGER :: Lay               ! Layer number
  INTEGER :: MovedSurfs        ! Number of Moved Surfaces (when sorting into hierarchical structure)
  LOGICAL :: SurfError=.false. ! General Surface Error, causes fatal error at end of routine
  INTEGER :: Loop
  INTEGER :: BaseSurfNum
  INTEGER :: TotLay            ! Total layers in a construction
  INTEGER :: TotLayFound       ! Total layers in the construction of a matching interzone surface
  INTEGER :: TotDetachedFixed  ! Total Shading:Site:Detailed entries
  INTEGER :: TotDetachedBldg   ! Total Shading:Building:Detailed entries
  INTEGER :: TotRectDetachedFixed  ! Total Shading:Site entries
  INTEGER :: TotRectDetachedBldg   ! Total Shading:Building entries
  INTEGER :: TotHTSurfs        ! Number of BuildingSurface:Detailed items to obtain
  INTEGER :: TotDetailedWalls  ! Number of Wall:Detailed items to obtain
  INTEGER :: TotDetailedRoofs  ! Number of RoofCeiling:Detailed items to obtain
  INTEGER :: TotDetailedFloors ! Number of Floor:Detailed items to obtain
  INTEGER :: TotHTSubs         ! Number of FenestrationSurface:Detailed items to obtain
  INTEGER :: TotShdSubs        ! Number of Shading:Zone:Detailed items to obtain
  INTEGER :: TotIntMass        ! Number of InternalMass items to obtain
  ! Simple Surfaces (Rectangular)
  INTEGER :: TotRectExtWalls   ! Number of Exterior Walls to obtain
  INTEGER :: TotRectIntWalls   ! Number of Adiabatic Walls to obtain
  INTEGER :: TotRectIZWalls    ! Number of Interzone Walls to obtain
  INTEGER :: TotRectUGWalls    ! Number of Underground to obtain
  INTEGER :: TotRectRoofs      ! Number of Roofs to obtain
  INTEGER :: TotRectCeilings   ! Number of Adiabatic Ceilings to obtain
  INTEGER :: TotRectIZCeilings ! Number of Interzone Ceilings to obtain
  INTEGER :: TotRectGCFloors   ! Number of Floors with Ground Contact to obtain
  INTEGER :: TotRectIntFloors  ! Number of Adiabatic Walls to obtain
  INTEGER :: TotRectIZFloors   ! Number of Interzone Floors to obtain
  INTEGER :: TotRectWindows
  INTEGER :: TotRectDoors
  INTEGER :: TotRectGlazedDoors
  INTEGER :: TotRectIZWindows
  INTEGER :: TotRectIZDoors
  INTEGER :: TotRectIZGlazedDoors
  INTEGER :: TotOverhangs
  INTEGER :: TotOverhangsProjection
  INTEGER :: TotFins
  INTEGER :: TotFinsProjection
  CHARACTER(len=20) ClassMsg
  CHARACTER(len=20) Msg2
  INTEGER :: OpaqueHTSurfs     ! Number of floors, walls and roofs in a zone
  INTEGER :: OpaqueHTSurfsWithWin ! Number of floors, walls and roofs with windows in a zone
  INTEGER :: InternalMassSurfs ! Number of internal mass surfaces in a zone
  LOGICAL :: RelWarning=.false.
  INTEGER :: ConstrNumSh       ! Shaded construction number for a window
  INTEGER :: LayNumOutside     ! Outside material numbers for a shaded construction
  INTEGER :: BlNum             ! Blind number
  LOGICAL :: WinShadingCtrlReferenced ! True if a WindowShadingControl is referenced by at least one window
  INTEGER :: ShadingCtrl       ! WindowShadingControl number
  INTEGER :: AddedSubSurfaces  ! Subsurfaces (windows) added when windows reference Window5 Data File
                               ! entries with two glazing systems
  INTEGER :: NeedToAddSurfaces ! Surfaces that will be added due to "unentered" other zone surface
  INTEGER :: NeedToAddSubSurfaces ! SubSurfaces that will be added due to "unentered" other zone surface
  INTEGER :: CurNewSurf
  INTEGER :: FirstTotalSurfaces
  INTEGER :: NVert
  INTEGER :: Vert
  INTEGER :: N
  REAL(r64) SurfWorldAz
  REAL(r64) :: surfTilt

  INTEGER :: MultFound, MultSurfNum
  CHARACTER(len=20) :: MultString
  LOGICAL,SAVE :: WarningDisplayed=.false.
  INTEGER, SAVE :: ErrCount1=0
  INTEGER, SAVE :: ErrCount2=0
  INTEGER, SAVE :: ErrCount3=0
  INTEGER, SAVE :: ErrCount4=0  ! counts of interzone area mismatches.
  LOGICAL :: SubSurfaceSevereDisplayed
 ! INTEGER :: Warning4Count=0  ! counts of nonmatched flat surface subsurface orientations
 ! INTEGER :: Warning5Count=0  ! counts of nonmatched flat surface subsurface orientations - could not be resolved
  LOGICAL :: errFlag

  INTEGER :: iTmp1
  INTEGER :: iTmp2
!unused  INTEGER :: SchID
  INTEGER :: BlNumNew
  INTEGER :: WinShadingControlPtr
  INTEGER :: ShadingType
!unused  REAL(r64) :: SchSlatAngle = 0.0D0
!unused  LOGICAL :: initmsg
  INTEGER :: errCount
  REAL(r64) :: diffp
!  TYPE (vector), ALLOCATABLE, DIMENSION(:) :: TestVertex
!  INTEGER :: Vrt
!  INTEGER :: testV
!  INTEGER :: testVsave
!  INTEGER :: countSides
!  INTEGER :: LLCVrt
!  REAL(r64) :: maxX
!  REAL(r64) :: maxY
!  REAL(r64) :: testX
!  REAL(r64) :: testY
  REAL(r64) :: surfAzimuth
!  LOGICAL :: Located
  LOGICAL :: sameSurfNormal
  LOGICAL :: izConstDiff  ! differences in construction for IZ surfaces
  LOGICAL :: izConstDiffMsg  ! display message about hb diffs only once.

          ! FLOW:
! Get the total number of surfaces to allocate derived type and for surface loops

  CALL GetGeometryParameters(ErrorsFound)

  IF (WorldCoordSystem) THEN
    IF (BuildingAzimuth /= 0.0d0) RelWarning=.true.
    DO ZoneNum=1,NumOfZones
      IF (Zone(ZoneNum)%RelNorth /= 0.0d0) RelWarning=.true.
    ENDDO
    IF (RelWarning .and. .not. WarningDisplayed) THEN
      CALL ShowWarningError(RoutineName//'World Coordinate System selected.  '// &
                            'Any non-zero Building/Zone North Axes or non-zero Zone Origins are ignored.')
      CALL ShowContinueError('These may be used in daylighting reference point coordinate calculations '//  &
         ' but not in normal geometry inputs.')
      WarningDisplayed=.true.
    ENDIF
    RelWarning=.false.
    DO ZoneNum=1,NumOfZones
      IF (Zone(ZoneNum)%OriginX /= 0.0d0) RelWarning=.true.
      IF (Zone(ZoneNum)%OriginY /= 0.0d0) RelWarning=.true.
      IF (Zone(ZoneNum)%OriginZ /= 0.0d0) RelWarning=.true.
    ENDDO
    IF (RelWarning .and. .not. WarningDisplayed) THEN
      CALL ShowWarningError(RoutineName//'World Coordinate System selected.  '// &
                            'Any non-zero Building/Zone North Axes or non-zero Zone Origins are ignored.')
      CALL ShowContinueError('These may be used in daylighting reference point coordinate calculations '//  &
         ' but not in normal geometry inputs.')
      WarningDisplayed=.true.
    ENDIF
  ENDIF


  TotDetachedFixed      =GetNumObjectsFound('Shading:Site:Detailed')
  TotDetachedBldg       =GetNumObjectsFound('Shading:Building:Detailed')
  TotRectDetachedFixed  =GetNumObjectsFound('Shading:Site')
  TotRectDetachedBldg   =GetNumObjectsFound('Shading:Building')
  TotHTSurfs            =GetNumObjectsFound('BuildingSurface:Detailed')
  TotDetailedWalls      =GetNumObjectsFound('Wall:Detailed')
  TotDetailedRoofs      =GetNumObjectsFound('RoofCeiling:Detailed')
  TotDetailedFloors     =GetNumObjectsFound('Floor:Detailed')
  TotHTSubs             =GetNumObjectsFound('FenestrationSurface:Detailed')
  TotShdSubs            =GetNumObjectsFound('Shading:Zone:Detailed')
  TotOverhangs          =GetNumObjectsFound('Shading:Overhang')
  TotOverhangsProjection=GetNumObjectsFound('Shading:Overhang:Projection')
  TotFins               =GetNumObjectsFound('Shading:Fin')
  TotFinsProjection     =GetNumObjectsFound('Shading:Fin:Projection')
  TotIntMass            =GetNumObjectsFound('InternalMass')
  TotRectWindows        =GetNumObjectsFound('Window')
  TotRectDoors          =GetNumObjectsFound('Door')
  TotRectGlazedDoors    =GetNumObjectsFound('GlazedDoor')
  TotRectIZWindows      =GetNumObjectsFound('Window:Interzone')
  TotRectIZDoors        =GetNumObjectsFound('Door:Interzone')
  TotRectIZGlazedDoors  =GetNumObjectsFound('GlazedDoor:Interzone')
  TotRectExtWalls       =GetNumObjectsFound('Wall:Exterior')
  TotRectIntWalls       =GetNumObjectsFound('Wall:Adiabatic')
  TotRectIZWalls        =GetNumObjectsFound('Wall:Interzone')
  TotRectUGWalls        =GetNumObjectsFound('Wall:Underground')
  TotRectRoofs          =GetNumObjectsFound('Roof')
  TotRectCeilings       =GetNumObjectsFound('Ceiling:Adiabatic')
  TotRectIZCeilings     =GetNumObjectsFound('Ceiling:Interzone')
  TotRectGCFloors       =GetNumObjectsFound('Floor:GroundContact')
  TotRectIntFloors      =GetNumObjectsFound('Floor:Adiabatic ')
  TotRectIZFloors       =GetNumObjectsFound('Floor:Interzone')

  TotOSC     =0

  TotSurfaces=(TotDetachedFixed+TotDetachedBldg+TotRectDetachedFixed+TotRectDetachedBldg)*2 + &
     TotHTSurfs + TotHTSubs + TotShdSubs*2 + TotIntMass +   &
     TotOverhangs*2 + TotOverhangsProjection*2 + TotFins*4 + TotFinsProjection*4 + &
     TotDetailedWalls + TotDetailedRoofs + TotDetailedFloors + &
     TotRectWindows + TotRectDoors + TotRectGlazedDoors + TotRectIZWindows + TotRectIZDoors + TotRectIZGlazedDoors + &
     TotRectExtWalls + TotRectIntWalls + TotRectIZWalls + TotRectUGWalls + &
     TotRectRoofs + TotRectCeilings + TotRectIZCeilings + &
     TotRectGCFloors + TotRectIntFloors + TotRectIZFloors

  ALLOCATE (SurfaceTmp(TotSurfaces))   ! Allocate the Surface derived type appropriately
    ! SurfaceTmp structure is allocated via derived type initialization.

  SurfNum=0
  AddedSubSurfaces=0
  AskForSurfacesReport=.true.

  CALL GetDetShdSurfaceData(ErrorsFound,SurfNum,TotDetachedFixed,TotDetachedBldg)

  CALL GetRectDetShdSurfaceData(ErrorsFound,SurfNum,TotRectDetachedFixed,TotRectDetachedBldg)

  CALL GetHTSurfaceData(ErrorsFound,SurfNum,TotHTSurfs,TotDetailedWalls,TotDetailedRoofs,TotDetailedFloors,  &
                 BaseSurfCls,BaseSurfIDs,NeedToAddSurfaces)

  CALL GetRectSurfaces(ErrorsFound,SurfNum,TotRectExtWalls,TotRectIntWalls,TotRectIZWalls,TotRectUGWalls,  &
      TotRectRoofs,TotRectCeilings,TotRectIZCeilings,TotRectGCFloors,TotRectIntFloors,TotRectIZFloors,     &
      BaseSurfIDs,NeedToAddSurfaces)

  CALL GetHTSubSurfaceData(ErrorsFound,SurfNum,TotHTSubs,SubSurfCls,SubSurfIDs,AddedSubSurfaces,NeedToAddSubSurfaces)

  CALL GetRectSubSurfaces(ErrorsFound,SurfNum,TotRectWindows,TotRectDoors,TotRectGlazedDoors,  &
      TotRectIZWindows,TotRectIZDoors,TotRectIZGlazedDoors,SubSurfIDs,AddedSubSurfaces,NeedToAddSubSurfaces)

  CALL GetAttShdSurfaceData(ErrorsFound,SurfNum,TotShdSubs)

  CALL GetSimpleShdSurfaceData(ErrorsFound,SurfNum,TotOverhangs,TotOverhangsProjection,TotFins,TotFinsProjection)

  CALL GetIntMassSurfaceData(ErrorsFound,SurfNum,TotIntMass)

  CALL GetMovableInsulationData(ErrorsFound)

  IF(CalcSolRefl) CALL GetShadingSurfReflectanceData(ErrorsFound)

  TotSurfaces=SurfNum + AddedSubSurfaces + NeedToAddSurfaces + NeedToAddSubSurfaces

  ! Have to make room for added surfaces, if needed
  FirstTotalSurfaces=SurfNum + AddedSubSurfaces
  IF (NeedToAddSurfaces+NeedToAddSubsurfaces > 0) THEN
    ALLOCATE(SurfaceTmpSave(TotSurfaces))
    SurfaceTmpSave(1:FirstTotalSurfaces)=SurfaceTmp
    DEALLOCATE(SurfaceTmp)
    ALLOCATE(SurfaceTmp(TotSurfaces))
    SurfaceTmp=SurfaceTmpSave
    DEALLOCATE(SurfaceTmpSave)
  ENDIF

  ALLOCATE (SurfaceWindow(TotSurfaces))

! add the "need to add" surfaces
  if (NeedtoAddSurfaces+NeedToAddSubSurfaces > 0)   &
!Debug    write(outputfiledebug,*) ' need to add ',NeedtoAddSurfaces+NeedToAddSubSurfaces
  CurNewSurf=FirstTotalSurfaces
  DO SurfNum=1,FirstTotalSurfaces
    IF (SurfaceTmp(SurfNum)%ExtBoundCond /= UnenteredAdjacentZoneSurface) CYCLE
    ! Need to add surface
    CurNewSurf=CurNewSurf+1
!Debug    write(outputfiledebug,*) ' adding surface=',curnewsurf
    SurfaceTmp(CurNewSurf)=SurfaceTmp(SurfNum)
    !  Basic parameters are the same for both surfaces.
    Found=FindItemInList(SurfaceTmp(SurfNum)%ExtBoundCondName,Zone%Name,NumOfZones)
    IF (Found == 0) CYCLE
    SurfaceTmp(CurNewSurf)%Zone=Found
    SurfaceTmp(CurNewSurf)%ZoneName=Zone(Found)%Name
    ! Reverse Construction
    SurfaceTmp(CurNewSurf)%Construction=AssignReverseConstructionNumber(SurfaceTmp(SurfNum)%Construction,SurfError)
    SurfaceTmp(CurNewSurf)%ConstructionStoredInputValue  = SurfaceTmp(CurNewSurf)%Construction
    ! Reverse Vertices
    NVert=SurfaceTmp(SurfNum)%Sides
    DO Vert=1,SurfaceTmp(SurfNum)%Sides
      SurfaceTmp(CurNewSurf)%Vertex(Vert)=SurfaceTmp(SurfNum)%Vertex(NVert)
      NVert=NVert-1
    ENDDO
    IF (SurfaceTmp(CurNewSurf)%Sides > 2) THEN
      CALL CreateNewellAreaVector(SurfaceTmp(CurNewSurf)%Vertex,SurfaceTmp(CurNewSurf)%Sides,  &
           SurfaceTmp(CurNewSurf)%NewellAreaVector)
      SurfaceTmp(CurNewSurf)%GrossArea=VecLength(SurfaceTmp(CurNewSurf)%NewellAreaVector)
      SurfaceTmp(CurNewSurf)%Area=SurfaceTmp(CurNewSurf)%GrossArea
      SurfaceTmp(CurNewSurf)%NetAreaShadowCalc = SurfaceTmp(CurNewSurf)%Area
      CALL CreateNewellSurfaceNormalVector(SurfaceTmp(CurNewSurf)%Vertex,SurfaceTmp(CurNewSurf)%Sides,  &
           SurfaceTmp(CurNewSurf)%NewellSurfaceNormalVector)
      CALL DetermineAzimuthAndTilt(SurfaceTmp(CurNewSurf)%Vertex,SurfaceTmp(CurNewSurf)%Sides,SurfWorldAz,SurfTilt,  &
                                   SurfaceTmp(CurNewSurf)%lcsx,SurfaceTmp(CurNewSurf)%lcsy,SurfaceTmp(CurNewSurf)%lcsz,  &
                                   SurfaceTmp(CurNewSurf)%GrossArea,SurfaceTmp(CurNewSurf)%NewellSurfaceNormalVector)
      SurfaceTmp(CurNewSurf)%Azimuth=SurfWorldAz
      SurfaceTmp(CurNewSurf)%Tilt=SurfTilt

      ! Sine and cosine of azimuth and tilt
      SurfaceTmp(CurNewSurf)%SinAzim = SIN(SurfWorldAz*DegToRadians)
      SurfaceTmp(CurNewSurf)%CosAzim = COS(SurfWorldAz*DegToRadians)
      SurfaceTmp(CurNewSurf)%SinTilt = SIN(SurfTilt*DegToRadians)
      SurfaceTmp(CurNewSurf)%CosTilt = COS(SurfTilt*DegToRadians)
      ! Outward normal unit vector (pointing away from room)
      SurfaceTmp(CurNewSurf)%OutNormVec = SurfaceTmp(CurNewSurf)%NewellSurfaceNormalVector
      DO N=1,3
        IF (ABS(SurfaceTmp(CurNewSurf)%OutNormVec(N)-1.0d0) < 1.d-06) SurfaceTmp(CurNewSurf)%OutNormVec(N) = +1.0d0
        IF (ABS(SurfaceTmp(CurNewSurf)%OutNormVec(N)+1.0d0) < 1.d-06) SurfaceTmp(CurNewSurf)%OutNormVec(N) = -1.0d0
        IF (ABS(SurfaceTmp(CurNewSurf)%OutNormVec(N))     < 1.d-06) SurfaceTmp(CurNewSurf)%OutNormVec(N) =  0.0d0
      ENDDO

      ! Can perform tests on this surface here
      SurfaceTmp(CurNewSurf)%ViewFactorSky=0.5d0*(1.d0+SurfaceTmp(CurNewSurf)%CosTilt)
      SurfaceTmp(CurNewSurf)%ViewFactorGround=0.5d0*(1.d0-SurfaceTmp(CurNewSurf)%CosTilt)

      ! The following IR view factors are modified in subr. SkyDifSolarShading if there are shadowing
      ! surfaces
      SurfaceTmp(CurNewSurf)%ViewFactorSkyIR = SurfaceTmp(CurNewSurf)%ViewFactorSky
      SurfaceTmp(CurNewSurf)%ViewFactorGroundIR = 0.5d0*(1.d0-SurfaceTmp(CurNewSurf)%CosTilt)
    ENDIF


    ! Change Name
    SurfaceTmp(CurNewSurf)%Name='iz-'//TRIM(SurfaceTmp(SurfNum)%Name)
!Debug   write(outputfiledebug,*) ' new surf name=',trim(SurfaceTmp(CurNewSurf)%Name)
!Debug   write(outputfiledebug,*) ' new surf in zone=',trim(surfacetmp(curnewsurf)%zoneName)
    SurfaceTmp(CurNewSurf)%ExtBoundCond=UnreconciledZoneSurface
    SurfaceTmp(SurfNum)%ExtBoundCond=UnreconciledZoneSurface
    SurfaceTmp(CurNewSurf)%ExtBoundCondName=SurfaceTmp(SurfNum)%Name
    SurfaceTmp(SurfNum)%ExtBoundCondName=SurfaceTmp(CurNewSurf)%Name
    IF (SurfaceTmp(CurNewSurf)%Class == SurfaceClass_Roof .or.   &
        SurfaceTmp(CurNewSurf)%Class == SurfaceClass_Wall .or.   &
        SurfaceTmp(CurNewSurf)%Class == SurfaceClass_Floor) THEN
        ! base surface
        IF (SurfaceTmp(SurfNum)%Class == SurfaceClass_Roof) THEN
          SurfaceTmp(CurNewSurf)%Class=SurfaceClass_Floor
!Debug          write(outputfiledebug,*) ' new surfaces is a floor'
        ELSE IF (SurfaceTmp(SurfNum)%Class == SurfaceClass_Floor) THEN
          SurfaceTmp(CurNewSurf)%Class=SurfaceClass_Roof
!Debug          write(outputfiledebug,*) ' new surfaces is a roof'
        ENDIF
        SurfaceTmp(CurNewSurf)%BaseSurf=CurNewSurf
        SurfaceTmp(CurnewSurf)%BaseSurfName=SurfaceTmp(CurNewSurf)%Name
!Debug        write(outputfiledebug,*) ' basesurf, extboundcondname=',trim(SurfaceTmp(CurNewSurf)%ExtBoundCondName)
    ELSE
        ! subsurface
      Found=FindIteminList('iz-'//SurfaceTmp(SurfNum)%BaseSurfName,SurfaceTmp%Name,FirstTotalSurfaces+CurNewSurf-1)
      IF (Found > 0) THEN
        SurfaceTmp(CurNewSurf)%BaseSurfName='iz-'//SurfaceTmp(SurfNum)%BaseSurfName
        SurfaceTmp(CurNewSurf)%BaseSurf=Found
        SurfaceTmp(Found)%Area =  &
               SurfaceTmp(Found)%Area - SurfaceTmp(CurNewSurf)%Area
        IF (SurfaceTmp(CurNewSurf)%Class == SurfaceClass_Window .OR.SurfaceTmp(CurNewSurf)%Class == SurfaceClass_GlassDoor) THEN
          SurfaceTmp(Found)%NetAreaShadowCalc =  &
          SurfaceTmp(Found)%NetAreaShadowCalc - SurfaceTmp(CurNewSurf)%Area/ &
            SurfaceTmp(CurNewSurf)%Multiplier
        ELSE ! Door, TDD:Diffuser, TDD:DOME
          SurfaceTmp(Found)%NetAreaShadowCalc =  &
          SurfaceTmp(Found)%NetAreaShadowCalc - SurfaceTmp(CurNewSurf)%Area
        ENDIF
        SurfaceTmp(CurNewSurf)%ExtBoundCond=SurfaceTmp(Found)%ExtBoundCond
        SurfaceTmp(CurNewSurf)%ExtBoundCondName=SurfaceTmp(SurfNum)%Name
        SurfaceTmp(CurNewSurf)%ExtSolar=SurfaceTmp(Found)%ExtSolar
        SurfaceTmp(CurNewSurf)%ExtWind=SurfaceTmp(Found)%ExtWind
        SurfaceTmp(CurNewSurf)%Zone=SurfaceTmp(Found)%Zone
        SurfaceTmp(CurNewSurf)%ZoneName=SurfaceTmp(Found)%ZoneName
        SurfaceTmp(CurNewSurf)%OSCPtr=SurfaceTmp(Found)%OSCPtr
!Debug        write(outputfiledebug,*) ' subsurf, extboundcondname=',trim(SurfaceTmp(CurNewSurf)%ExtBoundCondName)
!Debug        write(outputfiledebug,*) ' subsurf, basesurf=',trim('iz-'//SurfaceTmp(SurfNum)%BaseSurfName)
      ELSE
        CALL ShowSevereError(RoutineName//'Adding unentered subsurface, could not find base surface='// &
            TRIM('iz-'//SurfaceTmp(SurfNum)%BaseSurfName))
        SurfError=.true.
      ENDIF
    ENDIF

  ENDDO
!**********************************************************************************
! After all of the surfaces have been defined then the base surfaces for the
! sub-surfaces can be defined.  Loop through surfaces and match with the sub-surface
! names.
  DO SurfNum= 1, TotSurfaces
    IF (.not. SurfaceTmp(SurfNum)%HeatTransSurf) CYCLE

    ! why are we doing this again?  this should have already been done.
    IF (SameString(SurfaceTmp(SurfNum)%BaseSurfName,SurfaceTmp(SurfNum)%Name)) THEN
      Found=SurfNum
    ELSE
      Found=FindIteminList(SurfaceTmp(SurfNum)%BaseSurfName,SurfaceTmp%Name,TotSurfaces)
    ENDIF
    If (Found > 0) THEN
      SurfaceTmp(SurfNum)%BaseSurf=Found
      IF (SurfNum /= Found) THEN  ! for subsurfaces
        IF (SurfaceTmp(SurfNum)%HeatTransSurf) SurfaceTmp(Found)%NumSubSurfaces=SurfaceTmp(Found)%NumSubSurfaces+1
        IF (SurfaceTmp(SurfNum)%Class < SurfaceClass_Window .or.   &
            SurfaceTmp(SurfNum)%Class > SurfaceClass_TDD_Diffuser) THEN
          IF (SurfaceTmp(SurfNum)%Class == 0) THEN
            CALL ShowSevereError(RoutineName//'Invalid SubSurface detected, Surface='//TRIM(SurfaceTmp(SurfNum)%Name))
          ELSE
            CALL ShowSevereError(RoutineName//'Invalid SubSurface detected, Surface='//TRIM(SurfaceTmp(SurfNum)%Name)//  &
               ', class='//TRIM(BaseSurfCls(SurfaceTmp(SurfNum)%Class))//' invalid class for subsurface')
            SurfError=.true.
          ENDIF
        ENDIF
      ENDIF
    End If

  END DO  ! ...end of the Surface DO loop for finding BaseSurf
!**********************************************************************************

!**********************************************************************************
! orientation of flat subsurfaces (window/door/etc) need to match base surface
! CR8628
!  ALLOCATE(TestVertex(4)) ! subsurfaces we will look at have max of 4 vertices
  DO SurfNum=1,TotSurfaces
    IF (.not. SurfaceTmp(SurfNum)%HeatTransSurf) CYCLE
    ! If flat surface
    surfAzimuth = SurfaceTmp(SurfNum)%Azimuth
    surfTilt    = SurfaceTmp(SurfNum)%Tilt
    IF (ABS(surfTilt) <= 1.d-5 .or. ABS(surfTilt-180.d0) <= 1.d-5)  THEN
      ! see if there are any subsurfaces on roofs/floors
      DO itmp1=1,TotSurfaces
        IF (itmp1 == SurfNum) CYCLE
        IF (.not. SurfaceTmp(itmp1)%BaseSurf == SurfNum) CYCLE
        IF (.not. SurfaceTmp(itmp1)%HeatTransSurf) CYCLE
!          write(outputfiledebug,'(A)') 'roof/floor basesurface='//trim(SurfaceTmp(SurfNum)%Name)
!          write(outputfiledebug,'(A,3f7.2)') 'basesurface lc vectors=',SurfaceTmp(SurfNum)%lcsx
!          write(outputfiledebug,'(3f7.2)') SurfaceTmp(SurfNum)%lcsy
!          write(outputfiledebug,'(3f7.2)') SurfaceTmp(SurfNum)%lcsz
!          write(outputfiledebug,'(A,3f7.2)') 'basesurface surfnorm=',SurfaceTmp(SurfNum)%NewellSurfaceNormalVector
!          write(outputfiledebug,'(A)') 'subsurface='//trim(SurfaceTmp(itmp1)%Name)
!          write(outputfiledebug,'(A,3f7.2)') 'subsurface lc vectors=',SurfaceTmp(itmp1)%lcsx
!          write(outputfiledebug,'(3f7.2)') SurfaceTmp(itmp1)%lcsy
!          write(outputfiledebug,'(3f7.2)') SurfaceTmp(itmp1)%lcsz
!          write(outputfiledebug,'(A,3f7.2)') 'subsurface surfnorm=',SurfaceTmp(itmp1)%NewellSurfaceNormalVector
        IF (ABS(SurfaceTmp(itmp1)%Azimuth-surfAzimuth) <= 10.d0) CYCLE
        CALL CompareTwoVectors(SurfaceTmp(SurfNum)%NewellSurfaceNormalVector,SurfaceTmp(itmp1)%NewellSurfaceNormalVector,  &
           sameSurfNormal,.001d0)
        IF (sameSurfNormal) THEN  ! copy lcs vectors
          SurfaceTmp(itmp1)%lcsx=SurfaceTmp(SurfNum)%lcsx
          SurfaceTmp(itmp1)%lcsy=SurfaceTmp(SurfNum)%lcsy
          SurfaceTmp(itmp1)%lcsy=SurfaceTmp(SurfNum)%lcsy
          CYCLE
        ENDIF
!        IF (ABS(SurfaceTmp(itmp1)%Azimuth-360.0d0) < .01d0) THEN
!          SurfaceTmp(itmp1)%Azimuth=360.0d0-SurfaceTmp(itmp1)%Azimuth
!        ENDIF
!        IF (ABS(surfAzimuth-360.0d0) < .01d0) THEN
!          surfAzimuth=360.0d0-surfAzimuth
!          SurfaceTmp(SurfNum)%Azimuth=surfAzimuth
!        ENDIF
!        IF (ABS(SurfaceTmp(itmp1)%Azimuth-surfAzimuth) <= 10.d0) CYCLE
        ! have subsurface of base surface
        ! warning error
!        Warning4Count=Warning4Count+1
!        IF (Warning4Count == 1 .and. .not. DisplayExtraWarnings) THEN
!          CALL ShowSevereError(Routinename//'Some Outward Facing angles of subsurfaces differ '//  &
!                               'significantly from flat roof/floor base surface.')
!          CALL ShowContinueError('Fixes will be attempted to align subsurface with base surface.')
!          CALL ShowContinueError('...use Output:Diagnostics,DisplayExtraWarnings; '//  &
!                   'to show more details on individual surfaces.')
!        ENDIF
        IF (DisplayExtraWarnings) THEN
          CALL ShowSevereError(Routinename//'Outward facing angle ['//  &
               TRIM(RoundSigDigits(SurfaceTmp(itmp1)%Azimuth,3))// &
               '] of subsurface="'//TRIM(SurfaceTmp(itmp1)%Name)//  &
               '" significantly different than')
          CALL ShowContinueError('..facing angle ['//TRIM(RoundSigDigits(SurfaceTmp(SurfNum)%Azimuth,3))//  &
              '] of base surface='//TRIM(SurfaceTmp(SurfNum)%Name))
          CALL ShowContinueError('..surface class of base surface='//TRIM(cSurfaceClass(SurfaceTmp(SurfNum)%Class)))
!          CALL ShowContinueError('Fixes will be attempted to align subsurface with base surface.')
        ENDIF
!        Vrt=1
!        testV=2
!        testVsave=2
!        Located=.false.
!        DO CountSides=1,SurfaceTmp(itmp1)%Sides
!          DO Vrt=1,SurfaceTmp(itmp1)%Sides
!            TestVertex(Vrt)=SurfaceTmp(itmp1)%Vertex(testV)
!            testV=testV+1
!            if (testV > SurfaceTmp(itmp1)%Sides) testV=1
!          ENDDO
!          CALL CreateNewellSurfaceNormalVector(TestVertex,SurfaceTmp(itmp1)%Sides,  &
!                SurfaceTmp(itmp1)%NewellSurfaceNormalVector)
!          CALL DetermineAzimuthAndTilt(TestVertex,SurfaceTmp(itmp1)%Sides,SurfWorldAz,surfTilt,  &
!                                SurfaceTmp(itmp1)%lcsx,SurfaceTmp(itmp1)%lcsy,SurfaceTmp(itmp1)%lcsz,  &
!                                SurfaceTmp(itmp1)%GrossArea,SurfaceTmp(itmp1)%NewellSurfaceNormalVector)
!          IF (ABS(surfAzimuth-surfWorldAz) <= 1.d-5) THEN  ! found it
!            DO Vrt=1,SurfaceTmp(itmp1)%Sides
!              SurfaceTmp(itmp1)%Vertex(Vrt)=TestVertex(Vrt)
!            ENDDO
!            SurfaceTmp(itmp1)%Azimuth=SurfWorldAz
!            SurfaceTmp(itmp1)%Tilt=surfTilt
!            Located=.true.
!            EXIT
!          ENDIF
!          testV=testVsave+1
!          IF (testV > SurfaceTmp(itmp1)%Sides) EXIT
!        ENDDO
!        IF (.not. Located) THEN
!          Warning5Count=Warning5Count+1
!          ! another warning
!          IF (DisplayExtraWarnings) THEN
!            CALL ShowContinueError('Fix could not be accomplished.  Original orientation is retained.')
!          ENDIF
!          CALL CreateNewellSurfaceNormalVector(SurfaceTmp(itmp1)%Vertex,SurfaceTmp(itmp1)%Sides,  &
!                  SurfaceTmp(itmp1)%NewellSurfaceNormalVector)
!          CALL DetermineAzimuthAndTilt(SurfaceTmp(itmp1)%Vertex,SurfaceTmp(itmp1)%Sides,SurfWorldAz,surfTilt,  &
!                                SurfaceTmp(itmp1)%lcsx,SurfaceTmp(itmp1)%lcsy,SurfaceTmp(itmp1)%lcsz,  &
!                                SurfaceTmp(itmp1)%GrossArea,SurfaceTmp(itmp1)%NewellSurfaceNormalVector)
!          SurfaceTmp(itmp1)%Azimuth=SurfWorldAz
!          SurfaceTmp(itmp1)%Tilt=surfTilt
!        ENDIF
      ENDDO
    ENDIF
  ENDDO
!  IF (Warning5Count > 0) THEN
!    CALL ShowMessage(RoutineName//'There were '//trim(RoundSigDigits(Warning5Count))//  &
!       ' subsurfaces whose orientation (azimuth) could not be fixed to align with the base surface.')
!    CALL ShowMessage('Shadowing calculations may be inaccurate. Use Output:Diagnostics,DisplayExtraWarnings; for details.')
!  ENDIF
!  DEALLOCATE(TestVertex)

! The surfaces need to be hierarchical.  Input is allowed to be in any order.  In
! this section it is reordered into:

!    Detached shadowing surfaces
!    For each zone:
!      For each Wall
!        subsurfaces (windows, doors, shading) for that wall
!      For each Floor
!        subsurfaces for that floor
!      For each Roof
!        subsurfaces for that roof/ceiling
!      Internal Mass
!
!    After reordering, MovedSurfs should equal TotSurfaces

  MovedSurfs=0
  ALLOCATE (Surface(TotSurfaces))   ! Allocate the Surface derived type appropriately

  ! Move all Detached Surfaces to Front

  DO SurfNum=1,TotSurfaces
    IF (SurfaceTmp(SurfNum)%Class /= SurfaceClass_Detached_F .and.  &
        SurfaceTmp(SurfNum)%Class /= SurfaceClass_Detached_B .and.  &
        SurfaceTmp(SurfNum)%Class /= SurfaceClass_Shading) CYCLE

    !  A shading surface

    MovedSurfs=MovedSurfs+1
    Surface(MovedSurfs)=SurfaceTmp(SurfNum)
    SurfaceTmp(SurfNum)%Class=SurfaceClass_Moved !'Moved'
  ENDDO

  !  For each zone

  DO ZoneNum=1,NumOfZones

    !  For each Base Surface Type (Wall, Floor, Roof)

    DO Loop=1,3

      DO SurfNum=1,TotSurfaces

        IF (SurfaceTmp(SurfNum)%Zone == 0) CYCLE

        IF (.not. SameString(SurfaceTmp(SurfNum)%ZoneName,Zone(ZoneNum)%Name)) CYCLE
        IF (SurfaceTmp(SurfNum)%Class /= BaseSurfIDs(Loop)) CYCLE

        MovedSurfs=MovedSurfs+1
        Surface(MovedSurfs)=SurfaceTmp(SurfNum)
        SurfaceTmp(SurfNum)%Class=SurfaceClass_Moved ! 'Moved'
        SurfaceTmp(SurfNum)%BaseSurf=-1 ! Default has base surface = base surface
        BaseSurfNum=MovedSurfs
        Surface(MovedSurfs)%BaseSurf=BaseSurfNum

        !  Find all subsurfaces to this surface
        DO SubSurfNum=1,TotSurfaces

          IF (SurfaceTmp(SubSurfNum)%Zone == 0) CYCLE
          IF (SurfaceTmp(SubSurfNum)%BaseSurf /= SurfNum) CYCLE

          MovedSurfs=MovedSurfs+1
          Surface(MovedSurfs)=SurfaceTmp(SubSurfNum)
          SurfaceTmp(SubSurfNum)%Class=SurfaceClass_Moved ! 'Moved'
          Surface(MovedSurfs)%BaseSurf=BaseSurfNum
          SurfaceTmp(SubSurfNum)%BaseSurf=-1
        ENDDO
      ENDDO
    ENDDO

    DO SurfNum=1,TotSurfaces

      IF (SurfaceTmp(SurfNum)%ZoneName /= Zone(ZoneNum)%Name) CYCLE
      IF (SurfaceTmp(SurfNum)%Class /= SurfaceClass_IntMass) CYCLE

      MovedSurfs=MovedSurfs+1
      Surface(MovedSurfs)=SurfaceTmp(SurfNum)
      Surface(MovedSurfs)%BaseSurf=MovedSurfs
      SurfaceTmp(SurfNum)%Class=SurfaceClass_Moved ! 'Moved'
    ENDDO
  ENDDO

  IF (MovedSurfs /= TotSurfaces) THEN
    WRITE(ClassMsg,*) MovedSurfs
    ClassMsg=ADJUSTL(ClassMsg)
    WRITE(Msg2,*) TotSurfaces
    Msg2=ADJUSTL(Msg2)
    CALL ShowSevereError(RoutineName//'Reordered # of Surfaces ('//TRIM(ClassMsg)//  &
       ') not = Total # of Surfaces ('//TRIM(Msg2)//')')
    SurfError=.true.
    DO Loop=1,TotSurfaces
      IF (SurfaceTmp(Loop)%Class /= SurfaceClass_Moved) THEN
         IF (SurfaceTmp(Loop)%Class > 100) THEN
           CALL ShowSevereError(RoutineName//'Error in Surface= "'//TRIM(SurfaceTmp(Loop)%Name)//  &
               '" Class='//TRIM(cSurfaceClass(SurfaceTmp(Loop)%Class-100))// &
               ' indicated Zone="'//TRIM(SurfaceTmp(Loop)%ZoneName)//'"')
        ENDIF
      ENDIF
    ENDDO
    CALL ShowWarningError(RoutineName//'Remaining surface checks will use "reordered number of surfaces", '//  &
       'not number of original surfaces')
  ENDIF

  DEALLOCATE (SurfaceTmp)     ! DeAllocate the Temp Surface derived type


  !  For each Base Surface Type (Wall, Floor, Roof)

  DO Loop=1,3

    DO SurfNum=1,TotSurfaces

      IF (Surface(SurfNum)%Zone == 0) CYCLE

      IF (Surface(SurfNum)%Class /= BaseSurfIDs(Loop)) CYCLE

      !  Find all subsurfaces to this surface
      DO SubSurfNum=1,TotSurfaces

        IF (SurfNum == SubSurfNum) CYCLE
        IF (Surface(SubSurfNum)%Zone == 0) CYCLE
        IF (Surface(SubSurfNum)%BaseSurf /= SurfNum) CYCLE

        ! Check facing angle of Sub compared to base
        ! ignore problems of subsurfaces on roofs/ceilings/floors with azimuth
!          IF (Surface(SurfNum)%Class == SurfaceClass_Roof .or. Surface(SurfNum)%Class == SurfaceClass_Floor) CYCLE
!          write(outputfiledebug,'(A)') 'basesurface='//trim(surface(SurfNum)%Name)
!          write(outputfiledebug,'(A,3F7.2)') 'basesurface lc vectors=',Surface(SurfNum)%lcsx
!          write(outputfiledebug,'(3f7.2)') Surface(SurfNum)%lcsy
!          write(outputfiledebug,'(3f7.2)') Surface(SurfNum)%lcsz
!          write(outputfiledebug,'(A,3f7.2)') 'basesurface surfnorm=',Surface(SurfNum)%NewellSurfaceNormalVector
!          write(outputfiledebug,'(A)') 'subsurface='//trim(surface(SubSurfNum)%Name)
!          write(outputfiledebug,'(A,3F7.2)') 'subsurface lc vectors=',Surface(SubSurfNum)%lcsx
!          write(outputfiledebug,'(3f7.2)') Surface(SubSurfNum)%lcsy
!          write(outputfiledebug,'(3f7.2)') Surface(SubSurfNum)%lcsz
!          write(outputfiledebug,'(A,3f7.2)') 'subsurface surfnorm=',Surface(SubSurfNum)%NewellSurfaceNormalVector
        IF (ABS(Surface(SubSurfNum)%Azimuth-Surface(SurfNum)%Azimuth) <= 30.0d0) CYCLE
        CALL CompareTwoVectors(Surface(SurfNum)%NewellSurfaceNormalVector,Surface(SubSurfNum)%NewellSurfaceNormalVector,  &
           sameSurfNormal,.001d0)
        IF (sameSurfNormal) THEN  ! copy lcs vectors
          Surface(SubSurfNum)%lcsx=Surface(SurfNum)%lcsx
          Surface(SubSurfNum)%lcsy=Surface(SurfNum)%lcsy
          Surface(SubSurfNum)%lcsy=Surface(SurfNum)%lcsy
          CYCLE
        ENDIF
        IF (ABS(Surface(SubSurfNum)%Azimuth-360.0d0) < .01d0) THEN
          Surface(SubSurfNum)%Azimuth=360.0d0-Surface(SubSurfNum)%Azimuth
        ENDIF
        IF (ABS(Surface(SurfNum)%Azimuth-360.0d0) < .01d0) THEN
          Surface(SurfNum)%Azimuth=360.0d0-Surface(SurfNum)%Azimuth
        ENDIF
        IF (ABS(Surface(SubSurfNum)%Azimuth-Surface(SurfNum)%Azimuth) > 30.0d0) THEN
          IF (ABS(Surface(SurfNum)%SinTilt) > .17d0) THEN
            ErrCount1=ErrCount1+1
            IF (ErrCount1 == 1 .and. .not. DisplayExtraWarnings) THEN
              CALL ShowSevereError(Routinename//'Some Outward Facing angles of subsurfaces differ '//  &
                                   'significantly from base surface.')
              CALL ShowContinueError('...use Output:Diagnostics,DisplayExtraWarnings; '//  &
                       'to show more details on individual surfaces.')
            ENDIF
            IF (DisplayExtraWarnings) THEN
              CALL ShowSevereError(Routinename//'Outward facing angle ['//  &
                   TRIM(RoundSigDigits(Surface(SubSurfNum)%Azimuth,1))// &
                   '] of subsurface="'//TRIM(Surface(SubSurfNum)%Name)//  &
                   '" significantly different than')
              CALL ShowContinueError('..facing angle ['//TRIM(RoundSigDigits(Surface(SurfNum)%Azimuth,1))//  &
                  '] of base surface='//TRIM(Surface(SurfNum)%Name)//' Tilt='//TRIM(RoundSigDigits(Surface(SurfNum)%Tilt,1)))
              CALL ShowContinueError('..surface class of base surface='//TRIM(cSurfaceClass(Surface(SurfNum)%Class)))
            ENDIF
          ENDIF
!            SurfError=.true.
        ENDIF
      ENDDO
    ENDDO
  ENDDO

!**********************************************************************************
! Now, match up interzone surfaces
!
  NonMatch=.false.
  izConstDiffMsg=.false.
  DO SurfNum= 1, MovedSurfs !TotSurfaces
    !  Clean up Shading Surfaces, make sure they don't go through here.
    !  Shading surfaces have "Zone=0", should also have "BaseSurf=0"
    !  PGE: Revised so that shading surfaces can have BaseSurf /= 0 if they are daylighting shelves
    !       or other exterior reflecting surfaces.
    !IF (Surface(SurfNum)%Zone == 0) THEN
    !  Surface(SurfNum)%BaseSurf=0
    !  CYCLE
    !ENDIF
    IF (.not. Surface(SurfNum)%HeatTransSurf) CYCLE
    !   If other surface, match it up
    !  Both interzone and "internal" surfaces have this pointer set
    !  Internal surfaces point to themselves, Interzone to another
    IF (Surface(SurfNum)%ExtBoundCond == UnreconciledZoneSurface) THEN
      IF (Surface(SurfNum)%ExtBoundCondName /= '   ') THEN
        IF (Surface(SurfNum)%ExtBoundCondName == Surface(SurfNum)%Name) THEN
          Found=SurfNum
        ELSE
          Found=FindIteminList(Surface(SurfNum)%ExtBoundCondName,Surface%Name,MovedSurfs)
        ENDIF
        IF (Found /= 0) THEN
          Surface(SurfNum)%ExtBoundCond=Found
          ! Check that matching surface is also "OtherZoneSurface"
          IF (Surface(Found)%ExtBoundCond <= 0 .and. Surface(Found)%ExtBoundCond /= UnreconciledZoneSurface) THEN
            CALL ShowSevereError(RoutineName//'Potential "OtherZoneSurface" is not matched correctly:')

            CALL ShowContinueError('Surface='//TRIM(Surface(SurfNum)%Name)//', Zone='//TRIM(Surface(SurfNum)%ZoneName))
            CALL ShowContinueError('Nonmatched Other/InterZone Surface='//TRIM(Surface(Found)%Name)//', Zone='//  &
                                   TRIM(Surface(Found)%ZoneName))
            SurfError=.true.
          ENDIF
          ! Check that matching interzone surface has construction with reversed layers
          IF (Found /= SurfNum) THEN  ! Interzone surface
            ! Make sure different zones too (CR 4110)
            IF (Surface(SurfNum)%Zone == Surface(Found)%Zone) THEN
              ErrCount2=ErrCount2+1
              IF (ErrCount2 == 1 .and. .not. DisplayExtraWarnings) THEN
                CALL ShowWarningError(RoutineName//'CAUTION -- Interzone surfaces are occuring in the same zone(s).')
                CALL ShowContinueError('...use Output:Diagnostics,DisplayExtraWarnings; '//  &
                      'to show more details on individual occurrences.')
              ENDIF
              IF (DisplayExtraWarnings) THEN
                CALL ShowWarningError(RoutineName//'CAUTION -- Interzone surfaces are usually in different zones')
                CALL ShowContinueError('Surface='//TRIM(Surface(SurfNum)%Name)//', Zone='//TRIM(Surface(SurfNum)%ZoneName))
                CALL ShowContinueError('Surface='//TRIM(Surface(Found)%Name)//', Zone='//TRIM(Surface(Found)%ZoneName))
              ENDIF
            ENDIF
            ConstrNum = Surface(SurfNum)%Construction
            ConstrNumFound = Surface(Found)%Construction
            IF (ConstrNum <= 0 .or. ConstrNumFound <= 0) CYCLE
            IF (Construct(ConstrNum)%ReverseConstructionNumLayersWarning .and.   &
                Construct(ConstrNumFound)%ReverseConstructionNumLayersWarning) CYCLE
            IF (Construct(ConstrNum)%ReverseConstructionLayersOrderWarning .and.   &
                Construct(ConstrNumFound)%ReverseConstructionLayersOrderWarning) CYCLE
            TotLay = Construct(ConstrNum)%TotLayers
            TotLayFound = Construct(ConstrNumFound)%TotLayers
            IF(TotLay /= TotLayFound) THEN  ! Different number of layers
              ! match on like Uvalues (nominal)
              IF (ABS(NominalU(ConstrNum)-NominalU(ConstrNumFound)) > .001d0) THEN
                CALL ShowSevereError(RoutineName//'Construction '//TRIM(Construct(ConstrNum)%Name)// &
                                     ' of interzone surface '//TRIM(Surface(SurfNum)%Name)// &
                                     ' does not have the same number of layers as the construction '   &
                                     //TRIM(Construct(ConstrNumFound)%Name)//  &
                                     ' of adjacent surface '//TRIM(Surface(Found)%Name))
                IF (.not. Construct(ConstrNum)%ReverseConstructionNumLayersWarning .or.  &
                    .not. Construct(ConstrNumFound)%ReverseConstructionNumLayersWarning) THEN
                  CALL ShowContinueError('...this problem for this pair will not be reported again.')
                  Construct(ConstrNum)%ReverseConstructionNumLayersWarning=.true.
                  Construct(ConstrNumFound)%ReverseConstructionNumLayersWarning=.true.
                ENDIF
                SurfError=.true.
              ENDIF
            ELSE                            ! Same number of layers; check for reverse layers
              ! check layers as number of layers is the same
              izConstDiff=.false.
              ! ok if same nominal U
              DO Lay = 1,TotLay
                IF(Construct(ConstrNum)%LayerPoint(Lay) /=  &
                   Construct(ConstrNumFound)%LayerPoint(TotLay-Lay+1)) THEN
                   izConstDiff=.true.
                   EXIT  ! exit when diff
                  END IF
              END DO
              IF (izConstDiff .and. ABS(NominalU(ConstrNum)-NominalU(ConstrNumFound)) > .001d0) THEN
                CALL ShowSevereError(RoutineName//'Construction '//TRIM(Construct(ConstrNum)%Name)// &
                                    ' of interzone surface '//TRIM(Surface(SurfNum)%Name)// &
                                    ' does not have the same materials in the reverse order as the construction '   &
                                    //TRIM(Construct(ConstrNumFound)%Name)//  &
                                    ' of adjacent surface '//TRIM(Surface(Found)%Name))
                IF (.not. Construct(ConstrNum)%ReverseConstructionLayersOrderWarning .or.  &
                    .not. Construct(ConstrNumFound)%ReverseConstructionLayersOrderWarning) THEN
                  CALL ShowContinueError('...this problem for this pair will not be reported again.')
                  Construct(ConstrNum)%ReverseConstructionLayersOrderWarning=.true.
                  Construct(ConstrNumFound)%ReverseConstructionLayersOrderWarning=.true.
                ENDIF
                SurfError=.true.
              ELSEIF (izConstDiff) THEN
                CALL ShowWarningError(RoutineName//'Construction '//TRIM(Construct(ConstrNum)%Name)// &
                                         ' of interzone surface '//TRIM(Surface(SurfNum)%Name)// &
                                         ' does not have the same materials in the reverse order as the construction '   &
                                         //TRIM(Construct(ConstrNumFound)%Name)//  &
                                         ' of adjacent surface '//TRIM(Surface(Found)%Name))
                CALL ShowContinueError('...but Nominal U values are similar, diff=['//  &
                   trim(RoundSigDigits(ABS(NominalU(ConstrNum)-NominalU(ConstrNumFound)),4))//'] ... simulation proceeds.')
                IF (.not. izConstDiffMsg) THEN
                  CALL ShowContinueError('...if the two zones are expected to have significantly different temperatures, '//  &
                     'the proper "reverse" construction should be created.')
                  izConstDiffMsg=.true.
                ENDIF
                IF (.not. Construct(ConstrNum)%ReverseConstructionLayersOrderWarning .or.  &
                    .not. Construct(ConstrNumFound)%ReverseConstructionLayersOrderWarning) THEN
                  CALL ShowContinueError('...this problem for this pair will not be reported again.')
                  Construct(ConstrNum)%ReverseConstructionLayersOrderWarning=.true.
                  Construct(ConstrNumFound)%ReverseConstructionLayersOrderWarning=.true.
                ENDIF
              ENDIF
            END IF

            ! If significantly different areas -- this would not be good
            MultFound = Zone(Surface(Found)%Zone)%Multiplier * Zone(Surface(Found)%Zone)%ListMultiplier
            MultSurfNum = Zone(Surface(SurfNum)%Zone)%Multiplier * Zone(Surface(SurfNum)%Zone)%ListMultiplier
            IF (Surface(Found)%Area > 0.0d0) THEN
              IF (ABS((Surface(Found)%Area*MultFound - Surface(SurfNum)%Area*MultSurfNum)/  &
                       Surface(Found)%Area*MultFound) > .02d0) THEN  ! 2% difference in areas
                ErrCount4=ErrCount4+1
                IF (ErrCount4 == 1 .and. .not. DisplayExtraWarnings) THEN
                  CALL ShowWarningError(RoutineName//''//  &
                    'InterZone Surface Areas do not match as expected and might not satisfy conservation of energy:')
                  CALL ShowContinueError('...use Output:Diagnostics,DisplayExtraWarnings; '//  &
                       'to show more details on individual mismatches.')
                ENDIF
                IF (DisplayExtraWarnings) THEN
                  CALL ShowWarningError(RoutineName//''//  &
                    'InterZone Surface Areas do not match as expected and might not satisfy conservation of energy:')

                  IF (MultFound == 1 .and. MultSurfNum == 1) THEN
                    CALL ShowContinueError('  Area='//TRIM(TrimSigDigits(Surface(SurfNum)%Area,1))// &
                                           ' in Surface='//TRIM(Surface(SurfNum)%Name)// &
                                           ', Zone='//TRIM(Surface(SurfNum)%ZoneName))
                    CALL ShowContinueError('  Area='//TRIM(TrimSigDigits(Surface(Found)%Area,1))// &
                                           ' in Surface='//TRIM(Surface(Found)%Name)// &
                                           ', Zone='//TRIM(Surface(Found)%ZoneName))
                  ELSE ! Show multiplier info
                    WRITE(MultString,*) MultSurfNum
                    MultString=ADJUSTL(MultString)
                    CALL ShowContinueError('  Area='//TRIM(TrimSigDigits(Surface(SurfNum)%Area,1))// &
                                           ', Multipliers='//TRIM(MultString)// &
                                           ', Total Area='//TRIM(TrimSigDigits(Surface(SurfNum)%Area*MultSurfNum,1))// &
                                           ' in Surface='//TRIM(Surface(SurfNum)%Name)// &
                                           ' Zone='//TRIM(Surface(SurfNum)%ZoneName))
                    WRITE(MultString,*) MultFound
                    MultString=ADJUSTL(MultString)
                    CALL ShowContinueError('  Area='//TRIM(TrimSigDigits(Surface(Found)%Area,1))// &
                                           ', Multipliers='//TRIM(MultString)// &
                                           ', Total Area='//TRIM(TrimSigDigits(Surface(Found)%Area*MultFound,1))// &
                                           ' in Surface='//TRIM(Surface(Found)%Name)// &
                                           ' Zone='//TRIM(Surface(Found)%ZoneName))
                  ENDIF
                ENDIF
              ENDIF
            ENDIF
            ! Check opposites Azimuth and Tilt
            ! Tilt
            IF (ABS(ABS(Surface(Found)%Tilt+Surface(SurfNum)%Tilt)-180.d0) > 1.0d0) THEN
              CALL ShowWarningError(RoutineName//'InterZone Surface Tilts do not match as expected.')
              CALL ShowContinueError('  Tilt='//TRIM(TrimSigDigits(Surface(SurfNum)%Tilt,1))//  &
                                     ' in Surface='//TRIM(Surface(SurfNum)%Name)//', Zone='//TRIM(Surface(SurfNum)%ZoneName))
              CALL ShowContinueError('  Tilt='//TRIM(TrimSigDigits(Surface(Found)%Tilt,1))//  &
                                     ' in Surface='//TRIM(Surface(Found)%Name)//', Zone='//TRIM(Surface(Found)%ZoneName))
            ENDIF
            ! check surface class match.  interzone surface.
            IF ((Surface(SurfNum)%Class == SurfaceClass_Wall .and. Surface(Found)%Class /= SurfaceClass_Wall) .or.  &
                (Surface(SurfNum)%Class /= SurfaceClass_Wall .and. Surface(Found)%Class == SurfaceClass_Wall) ) THEN
              CALL ShowWarningError(RoutineName//'InterZone Surface Classes do not match as expected.')
              CALL ShowContinueError('Surface="'//trim(Surface(SurfNum)%Name)//'", surface class='//  &
                 TRIM(cSurfaceClass(Surface(SurfNum)%Class)))
              CALL ShowContinueError('Adjacent Surface="'//trim(Surface(Found)%Name)//'", surface class='//  &
                 TRIM(cSurfaceClass(Surface(Found)%Class)))
              CALL ShowContinueError('Other errors/warnings may follow about these surfaces.')
            ENDIF
            IF ((Surface(SurfNum)%Class == SurfaceClass_Roof .and. Surface(Found)%Class /= SurfaceClass_Floor) .or.  &
                (Surface(SurfNum)%Class /= SurfaceClass_Roof .and. Surface(Found)%Class == SurfaceClass_Floor) ) THEN
              CALL ShowWarningError(RoutineName//'InterZone Surface Classes do not match as expected.')
              CALL ShowContinueError('Surface="'//trim(Surface(SurfNum)%Name)//'", surface class='//  &
                 TRIM(cSurfaceClass(Surface(SurfNum)%Class)))
              CALL ShowContinueError('Adjacent Surface="'//trim(Surface(Found)%Name)//'", surface class='//  &
                 TRIM(cSurfaceClass(Surface(Found)%Class)))
              CALL ShowContinueError('Other errors/warnings may follow about these surfaces.')
            ENDIF
            IF (Surface(SurfNum)%Class /= SurfaceClass_Roof .and. Surface(SurfNum)%Class /= SurfaceClass_Floor) THEN
              ! Walls, Windows, Doors, Glass Doors
              IF (Surface(SurfNum)%Class /= SurfaceClass_Wall) THEN
                ! Surface is a Door, Window or Glass Door
                IF (Surface(SurfNum)%BaseSurf == 0) CYCLE   ! error detected elsewhere
                IF (Surface(Surface(SurfNum)%BaseSurf)%Class == SurfaceClass_Roof .or.   &
                    Surface(Surface(SurfNum)%BaseSurf)%Class == SurfaceClass_Floor) CYCLE
              ENDIF
              IF (ABS(ABS(Surface(SurfNum)%Azimuth-Surface(Found)%Azimuth)-180.d0) > 1.d0) THEN
                IF (ABS(Surface(SurfNum)%SinTilt) > .5d0 .or. DisplayExtraWarnings) THEN
                  ! if horizontal surfaces, then these are windows/doors/etc in those items.
                  CALL ShowWarningError(RoutineName//'InterZone Surface Azimuths do not match as expected.')
                  CALL ShowContinueError('  Azimuth='//TRIM(TrimSigDigits(Surface(SurfNum)%Azimuth,1))//  &
                                         ', Tilt='//TRIM(TrimSigDigits(Surface(SurfNum)%Tilt,1))//        &
                                         ', in Surface='//TRIM(Surface(SurfNum)%Name)//', Zone='//TRIM(Surface(SurfNum)%ZoneName))
                  CALL ShowContinueError('  Azimuth='//TRIM(TrimSigDigits(Surface(Found)%Azimuth,1))//  &
                                         ', Tilt='//TRIM(TrimSigDigits(Surface(Found)%Tilt,1))//        &
                                         ', in Surface='//TRIM(Surface(Found)%Name)//', Zone='//TRIM(Surface(Found)%ZoneName))
                  CALL ShowContinueError('..surface class of first surface='//TRIM(cSurfaceClass(Surface(SurfNum)%Class)))
                  CALL ShowContinueError('..surface class of second surface='//TRIM(cSurfaceClass(Surface(Found)%Class)))
                ENDIF
              ENDIF
            ELSE  ! Roofs, Floors
              ! should be looking at opposite tilts, not azimuth for roof/floor matches...
!              IF (ABS(ABS(Surface(SurfNum)%Azimuth+Surface(Found)%Azimuth)-360.) > 1.0d0) THEN
!                CALL ShowWarningError('InterZone Surface Azimuths do not match as expected.')
!                CALL ShowContinueError('  Azimuth='//TRIM(TrimSigDigits(Surface(SurfNum)%Azimuth,1))//  &
!                                       ' in Surface='//TRIM(Surface(SurfNum)%Name)//', Zone='//TRIM(Surface(SurfNum)%ZoneName))
!                CALL ShowContinueError('  Azimuth='//TRIM(TrimSigDigits(Surface(Found)%Azimuth,1))//  &
!                                       ' in Surface='//TRIM(Surface(Found)%Name)//', Zone='//TRIM(Surface(Found)%ZoneName))
!              ENDIF
            ENDIF

            ! Make sure exposures (Sun, Wind) are the same.....and are "not"
            IF (Surface(SurfNum)%ExtSolar .or. Surface(Found)%ExtSolar) THEN
              CALL ShowWarningError(RoutineName//'Interzone surfaces cannot be "SunExposed" -- removing SunExposed')
              CALL ShowContinueError('  Surface='//TRIM(Surface(SurfNum)%Name)//', Zone='//TRIM(Surface(SurfNum)%ZoneName))
              CALL ShowContinueError('  Surface='//TRIM(Surface(Found)%Name)//', Zone='//TRIM(Surface(Found)%ZoneName))
              Surface(SurfNum)%ExtSolar=.false.
              Surface(Found)%ExtSolar=.false.
            ENDIF
            IF (Surface(SurfNum)%ExtWind .or. Surface(Found)%ExtWind) THEN
              CALL ShowWarningError(RoutineName//'Interzone surfaces cannot be "WindExposed" -- removing WindExposed')
              CALL ShowContinueError('  Surface='//TRIM(Surface(SurfNum)%Name)//', Zone='//TRIM(Surface(SurfNum)%ZoneName))
              CALL ShowContinueError('  Surface='//TRIM(Surface(Found)%Name)//', Zone='//TRIM(Surface(Found)%ZoneName))
              Surface(SurfNum)%ExtWind=.false.
              Surface(Found)%ExtWind=.false.
            ENDIF
          END IF
          ! Set opposing surface back to this one (regardless of error)
          Surface(Found)%ExtBoundCond=SurfNum
          ! Check subsurfaces...  make sure base surface is also an interzone surface
          IF (Surface(SurfNum)%BaseSurf /= SurfNum) THEN  ! Subsurface
            IF (Surface(SurfNum)%ExtBoundCond /= SurfNum .and. Surface(SurfNum)%ExtBoundCondName /= '   ') THEN
              ! if not internal subsurface
              IF (Surface(Surface(SurfNum)%BaseSurf)%ExtBoundCond == Surface(SurfNum)%BaseSurf) THEN
                     ! base surface is not interzone surface
                CALL ShowSevereError(RoutineName//'SubSurface="'//TRIM(Surface(SurfNum)%Name)//'" is an interzone subsurface.')
                CALL ShowContinueError('..but the Base Surface is not an interzone surface, Surface="'//  &
                    TRIM(Surface(Surface(SurfNum)%BaseSurf)%Name)//'".')
                SurfError=.true.
              ENDIF
            ENDIF
          ENDIF
        Else
          !  Seems unlikely that an internal surface would be missing itself, so this message
          !  only indicates for adjacent (interzone) surfaces.
          CALL ShowSevereError(RoutineName//'Adjacent Surface not found: '//TRIM(Surface(SurfNum)%ExtBoundCondName)// &
                               ' adjacent to surface '//TRIM(Surface(SurfNum)%Name) )
          NonMatch=.true.
          SurfError=.true.
        End If
      ELSEIF (Surface(SurfNum)%BaseSurf /= SurfNum) THEN  ! Subsurface
        IF (Surface(Surface(SurfNum)%BaseSurf)%ExtBoundCond > 0 .and.    &       ! If Interzone surface, subsurface must be also.
            Surface(Surface(SurfNum)%BaseSurf)%ExtBoundCond /= Surface(SurfNum)%BaseSurf) THEN
          CALL ShowSevereError(RoutineName//'SubSurface on Interzone Surface must be an Interzone SubSurface.')
          CALL ShowContinueError('...OutsideFaceEnvironment is blank, in Surface='//TRIM(Surface(SurfNum)%Name))
          SurfError=.true.
        ELSE
          ErrCount3=ErrCount3+1
          IF (ErrCount3 == 1 .and. .not. DisplayExtraWarnings) THEN
            CALL ShowWarningError(RoutineName//'Blank name for Outside Boundary Condition Objects.')
            CALL ShowContinueError('...use Output:Diagnostics,DisplayExtraWarnings; to show more details on individual surfaces.')
          ENDIF
          IF (DisplayExtraWarnings) THEN
            CALL ShowWarningError(RoutineName//'Blank name for Outside Boundary Condition Object, in surface='//  &
                                  TRIM(Surface(SurfNum)%Name))
            CALL ShowContinueError('Resetting this surface to be an internal zone surface, zone='//TRIM(Surface(SurfNum)%ZoneName))
          ENDIF
          Surface(SurfNum)%ExtBoundCondName=Surface(SurfNum)%Name
          Surface(SurfNum)%ExtBoundCond=SurfNum
        ENDIF
      ELSE
        ErrCount3=ErrCount3+1
        IF (ErrCount3 == 1 .and. .not. DisplayExtraWarnings) THEN
          CALL ShowSevereError(RoutineName//'Blank name for Outside Boundary Condition Objects.')
          CALL ShowContinueError('...use Output:Diagnostics,DisplayExtraWarnings; to show more details on individual surfaces.')
        ENDIF
        IF (DisplayExtraWarnings) THEN
          CALL ShowWarningError(RoutineName//'Blank name for Outside Boundary Condition Object, in surface='//  &
                                TRIM(Surface(SurfNum)%Name))
          CALL ShowContinueError('Resetting this surface to be an internal zone (adiabatic) surface, zone='//  &
             TRIM(Surface(SurfNum)%ZoneName))
        ENDIF
        Surface(SurfNum)%ExtBoundCondName=Surface(SurfNum)%Name
        Surface(SurfNum)%ExtBoundCond=SurfNum
        SurfError=.true.
      ENDIF
    End If

  END DO  ! ...end of the Surface DO loop for finding BaseSurf
  If (NonMatch) THEN
    CALL ShowSevereError(RoutineName//'Non matching interzone surfaces found')
  End If

!**********************************************************************************
! Warn about interzone surfaces that have adiabatic windows/vice versa
  SubSurfaceSevereDisplayed=.false.
  DO SurfNum=1,TotSurfaces
    IF (.not. Surface(SurfNum)%HeatTransSurf) CYCLE
    IF (Surface(SurfNum)%BaseSurf == SurfNum) CYCLE  ! base surface
    ! not base surface.  Check it.
    IF (Surface(Surface(SurfNum)%BaseSurf)%ExtBoundCond <= 0) THEN  ! exterior or other base surface
      IF (Surface(SurfNum)%ExtBoundCond /= Surface(Surface(SurfNum)%BaseSurf)%ExtBoundCond) THEN ! should match base surface
        IF (Surface(SurfNum)%ExtBoundCond == SurfNum) THEN
          CALL ShowSevereError(RoutineName//'Subsurface="'//trim(Surface(SurfNum)%Name)//  &
             '" exterior condition [adiabatic surface] in a base surface="'//  &
             trim(Surface(Surface(SurfNum)%BaseSurf)%Name)//  &
             '" with exterior condition ['//  &
             trim(cExtBoundCondition(Surface(Surface(SurfNum)%BaseSurf)%ExtBoundCond))//']')
          SurfError=.true.
        ELSEIF (Surface(SurfNum)%ExtBoundCond > 0) THEN
          CALL ShowSevereError(RoutineName//'Subsurface="'//trim(Surface(SurfNum)%Name)//  &
             '" exterior condition [interzone surface] in a base surface="'//  &
             trim(Surface(Surface(SurfNum)%BaseSurf)%Name)//  &
             '" with exterior condition ['//  &
             trim(cExtBoundCondition(Surface(Surface(SurfNum)%BaseSurf)%ExtBoundCond))//']')
          SurfError=.true.
        ELSEIF (Surface(Surface(SurfNum)%BaseSurf)%ExtBoundCond == OtherSideCondModeledExt) THEN
          CALL ShowWarningError(RoutineName//'Subsurface="'//trim(Surface(SurfNum)%Name)//  &
           '" exterior condition ['//  &
           trim(cExtBoundCondition(Surface(SurfNum)%ExtBoundCond))//  &
           '] in a base surface="'//trim(Surface(Surface(SurfNum)%BaseSurf)%Name)//  &
           '" with exterior condition ['//  &
           trim(cExtBoundCondition(Surface(Surface(SurfNum)%BaseSurf)%ExtBoundCond))//']')
          CALL ShowContinueError('...SubSurface will not use the exterior condition model of the base surface.')
        ELSE
          CALL ShowSevereError(RoutineName//'Subsurface="'//trim(Surface(SurfNum)%Name)//  &
           '" exterior condition ['//  &
           trim(cExtBoundCondition(Surface(SurfNum)%ExtBoundCond))//  &
           '] in a base surface="'//trim(Surface(Surface(SurfNum)%BaseSurf)%Name)//  &
           '" with exterior condition ['//  &
           trim(cExtBoundCondition(Surface(Surface(SurfNum)%BaseSurf)%ExtBoundCond))//']')
          SurfError=.true.
        ENDIF
        IF (.not. SubSurfaceSevereDisplayed .and. SurfError) THEN
          CALL ShowContinueError('...calculations for heat balance would be compromised.')
          SubSurfaceSevereDisplayed=.true.
        ENDIF
      ENDIF
    ELSEIF (Surface(Surface(SurfNum)%BaseSurf)%BaseSurf == Surface(Surface(SurfNum)%BaseSurf)%ExtBoundCond) THEN
      ! adiabatic surface. make sure subsurfaces match
      IF (Surface(SurfNum)%ExtBoundCond /= SurfNum) THEN ! not adiabatic surface
        IF (Surface(SurfNum)%ExtBoundCond > 0) THEN
          CALL ShowSevereError(RoutineName//'Subsurface="'//trim(Surface(SurfNum)%Name)//  &
             '" exterior condition [interzone surface] in a base surface="'//  &
             trim(Surface(Surface(SurfNum)%BaseSurf)%Name)//  &
             '" with exterior condition [adiabatic surface]')
        ELSE
          CALL ShowSevereError(RoutineName//'Subsurface="'//trim(Surface(SurfNum)%Name)//  &
             '" exterior condition ['//  &
             trim(cExtBoundCondition(Surface(SurfNum)%ExtBoundCond))//  &
             '] in a base surface="'//trim(Surface(Surface(SurfNum)%BaseSurf)%Name)//  &
             '" with exterior condition [adiabatic surface]')
        ENDIF
        IF (.not. SubSurfaceSevereDisplayed) THEN
          CALL ShowContinueError('...calculations for heat balance would be compromised.')
          SubSurfaceSevereDisplayed=.true.
        ENDIF
        SurfError=.true.
      ENDIF
    ELSEIF (Surface(Surface(SurfNum)%BaseSurf)%ExtBoundCond > 0) THEN  ! interzone surface
      IF (Surface(SurfNum)%ExtBoundCond == SurfNum) THEN
        CALL ShowSevereError(RoutineName//'Subsurface="'//trim(Surface(SurfNum)%Name)//  &
           '" is an adiabatic surface in an Interzone base surface="'//trim(Surface(Surface(SurfNum)%BaseSurf)%Name)//'"')
        IF (.not. SubSurfaceSevereDisplayed) THEN
          CALL ShowContinueError('...calculations for heat balance would be compromised.')
          SubSurfaceSevereDisplayed=.true.
        ENDIF
!        SurfError=.true.
      ENDIF
    ENDIF
  ENDDO

!**********************************************************************************
!   Set up Zone Surface Pointers
  DO ZoneNum=1,NumOfZones
    DO SurfNum=1,MovedSurfs !TotSurfaces
      IF (Surface(SurfNum)%Zone == ZoneNum) THEN
        IF (Zone(ZoneNum)%SurfaceFirst == 0) THEN
          Zone(ZoneNum)%SurfaceFirst=SurfNum
          EXIT
        ENDIF
      ENDIF
    END DO
  END DO
  !  Surface First pointers are set, set last
  IF (NumOfZones > 0) THEN
    Zone(NumOfZones)%SurfaceLast=TotSurfaces
  ENDIF
  DO ZoneNum=1,NumOfZones-1
    Zone(ZoneNum)%SurfaceLast=Zone(ZoneNum+1)%SurfaceFirst-1
  END DO

  DO ZoneNum=1,NumOfZones
    IF (Zone(ZoneNum)%SurfaceFirst == 0) THEN
      CALL ShowSevereError(RoutineName//'Zone has no surfaces, Zone='//TRIM(Zone(ZoneNum)%Name))
      SurfError=.true.
    ENDIF
  ENDDO

! Set up Floor Areas for Zones
  IF (.not. SurfError) THEN
    DO ZoneNum=1,NumOfZones
      DO SurfNum=Zone(ZoneNum)%SurfaceFirst,Zone(ZoneNum)%SurfaceLast
        IF (Surface(SurfNum)%Class == SurfaceClass_Floor) THEN
          Zone(ZoneNum)%FloorArea=Zone(ZoneNum)%FloorArea+Surface(SurfNum)%Area
          Zone(ZoneNum)%HasFloor=.true.
        ENDIF
        IF (Surface(SurfNum)%Class == SurfaceClass_Roof) THEN
          Zone(ZoneNum)%HasRoof=.true.
        ENDIF
      END DO
    END DO
    errCount=0
    DO ZoneNum=1,NumOfZones
      Zone(ZoneNum)%CalcFloorArea = Zone(ZoneNum)%FloorArea
      IF (Zone(ZoneNum)%UserEnteredFloorArea /= AutoCalculate) THEN
      ! Check entered vs calculated
        IF (Zone(ZoneNum)%UserEnteredFloorArea > 0.0d0) THEN   ! User entered zone floor area,
                                                             ! produce message if not near calculated
          IF (Zone(ZoneNum)%CalcFloorArea > 0.0d0) THEN
            diffp=ABS(Zone(ZoneNum)%CalcFloorArea-Zone(ZoneNum)%UserEnteredFloorArea)/Zone(ZoneNum)%UserEnteredFloorArea
            IF (diffp  > .05d0) THEN
              ErrCount=ErrCount+1
              IF (ErrCount == 1 .and. .not. DisplayExtraWarnings) THEN
                CALL ShowWarningError(RoutineName//'Entered Zone Floor Areas differ from calculated Zone Floor Area(s).')
                CALL ShowContinueError('...use Output:Diagnostics,DisplayExtraWarnings; to show more details on individual zones.')
              ENDIF
              IF (DisplayExtraWarnings) THEN
                ! Warn user of using specified Zone Floor Area
                CALL ShowWarningError(RoutineName//'Entered Floor Area entered for Zone="'//TRIM(Zone(ZoneNum)%Name)// &
                            '" significantly different from calculated Floor Area')
                CALL ShowContinueError('Entered Zone Floor Area value='//  &
                            TRIM(RoundSigDigits(Zone(ZoneNum)%UserEnteredFloorArea,2))//  &
                            ', Calculated Zone Floor Area value='//TRIM(RoundSigDigits(Zone(ZoneNum)%CalcFloorArea,2))// &
                            ', entered Floor Area will be used in calculations.')
              ENDIF
            ENDIF
          ENDIF
          Zone(ZoneNum)%FloorArea = Zone(ZoneNum)%UserEnteredFloorArea
          Zone(ZoneNum)%HasFloor=.true.
        ENDIF
      ELSE
        Zone(ZoneNum)%FloorArea = Zone(ZoneNum)%CalcFloorArea  ! redundant, already done.
      ENDIF
    END DO
  ENDIF

  DO SurfNum=1,MovedSurfs !TotSurfaces
    IF (Surface(SurfNum)%Area < 1.d-06) THEN
      CALL ShowSevereError(RoutineName//'Zero or negative surface area['//trim(RoundSigDigits(Surface(SurfNum)%Area,5))//  &
         '], Surface='//Trim(Surface(SurfNum)%Name))
      SurfError=.true.
    ENDIF
    IF (Surface(SurfNum)%Area >= 1.d-06 .and. Surface(SurfNum)%Area < .001d0) THEN
      CALL ShowWarningError(RoutineName//'Very small surface area['//trim(RoundSigDigits(Surface(SurfNum)%Area,5))//  &
         '], Surface='//Trim(Surface(SurfNum)%Name))
    ENDIF
  END DO

  DO SurfNum=1,MovedSurfs !TotSurfaces
    ! GLASSDOORs and TDD:DIFFUSERs will be treated as windows in the subsequent heat transfer and daylighting
    ! calculations. Reset class to 'Window' after saving the original designation in SurfaceWindow.

    SurfaceWindow(SurfNum)%OriginalClass = Surface(SurfNum)%Class

    IF (Surface(SurfNum)%Class == SurfaceClass_GlassDoor &
      .OR. Surface(SurfNum)%Class == SurfaceClass_TDD_Diffuser) Surface(SurfNum)%Class = SurfaceClass_Window

    IF (Surface(SurfNum)%Class.EQ.SurfaceClass_TDD_Dome) THEN
      ! Reset the TDD:DOME subsurface to act as a base surface that can shade and be shaded
      ! NOTE: This must be set early so that subsequent shading calculations are done correctly
      Surface(SurfNum)%BaseSurf=SurfNum
    END IF
  END DO

  errFlag=.false.
  IF (.not. SurfError) THEN
    DO SurfNum=1,MovedSurfs !TotSurfaces
      ! Set ShadedConstruction numbers for windows whose shaded constructions were created
      ! when shading device was specified in the WindowShadingControl for the window
      IF(Surface(SurfNum)%ShadedConstruction /= 0) &
        SurfaceWindow(SurfNum)%ShadedConstruction = Surface(SurfNum)%ShadedConstruction

      ! no need to set the below -- it is the default
      ! Set variable that indicates if shading device has movable slats
!      SurfaceWindow(SurfNum)%MovableSlats = .FALSE.

      ! TH 2/9/2010. Fixed for CR 8010 for speed up purpose rather than fixing the problem
      WinShadingControlPtr = Surface(SurfNum)%WindowShadingControlPtr
      IF(WinShadingControlPtr /= 0) THEN
        IF(WindowShadingControl(WinShadingControlPtr)%SlatAngleControlForBlinds /= WSC_SAC_FixedSlatAngle) &
          SurfaceWindow(SurfNum)%MovableSlats = .TRUE.
        ! for a constant schedule of slat angle, it acts the same way as fixed angle
        ! TH 3/14/2011, CR 8347. Code was commented out due to the use of ExternalInterface (BCVTB)
        !IF(WindowShadingControl(WinShadingControlPtr)%SlatAngleControlForBlinds == WSC_SAC_ScheduledSlatAngle) THEN
          ! get schedule index
        !  SchID = WindowShadingControl(WinShadingControlPtr)%SlatAngleSchedule
        !  IF (SchID /= 0 ) THEN
        !    SchSlatAngle = GetScheduleMinValue(SchID)
        !    IF (SchSlatAngle == GetScheduleMaxValue(SchID)) THEN
        !      SurfaceWindow(SurfNum)%MovableSlats = .FALSE.
        !    ENDIF
        !  ENDIF
        !ENDIF
            ENDIF

      ConstrNumSh = SurfaceWindow(SurfNum)%ShadedConstruction
      IF(ConstrNumSh <= 0) CYCLE

      ShadingType = WindowShadingControl(WinShadingControlPtr)%ShadingType

      ! only for blinds
      IF(ShadingType == WSC_ST_ExteriorBlind .OR. ShadingType == WSC_ST_InteriorBlind &
        .OR. ShadingType == WSC_ST_BetweenGlassBlind ) THEN

        ! TH 1/7/2010. CR 7930
        ! The old code did not consider between-glass blind. Also there should not be two blinds - both interior and exterior
        ! Use the new generic code (assuming only one blind) as follows
        DO iTmp1 = 1, Construct(ConstrNumSh)%TotLayers
          iTmp2 = Construct(ConstrNumSh)%LayerPoint(iTmp1)
          IF(Material(iTmp2)%Group == WindowBlind) THEN
            BlNum = Material(iTmp2)%BlindDataPtr
            SurfaceWindow(SurfNum)%BlindNumber = BlNum
            ! TH 2/18/2010. CR 8010
            ! if it is a blind with movable slats, create one new blind and set it to VariableSlat if not done so yet.
            !  the new blind is created only once, it can be shared by multiple windows though.
            IF(SurfaceWindow(SurfNum)%MovableSlats .AND. Blind(BlNum)%SlatAngleType /= VariableSlats) THEN
              errFlag=.false.
              CALL AddVariableSlatBlind(BlNum,BlNumNew,errFlag)
              ! point to the new blind
              Material(iTmp2)%BlindDataPtr = BlNumNew
              ! window surface points to new blind
              SurfaceWindow(SurfNum)%BlindNumber = BlNumNew
            ENDIF
            EXIT
          END IF
        END DO

        IF (errFlag) THEN
          ErrorsFound=.true.
          CALL ShowContinueError('WindowProperty:ShadingControl '//  &
            TRIM(WindowShadingControl(WinShadingControlPtr)%Name)// &
            ' has errors, program will terminate.')
        ENDIF

        ! TH 5/17/2010. Fixed for CR 8121. Overwrite the blind slat angle with the constant scheduled value
        ! TH 3/14/2011. With fix for CR 8347, the following code is no longer needed.
        !IF (SurfaceWindow(SurfNum)%BlindNumber >0 .AND. WinShadingControlPtr >0 ) THEN
        !  IF (.NOT. SurfaceWindow(SurfNum)%MovableSlats .AND. &
        !    WindowShadingControl(WinShadingControlPtr)%SlatAngleControlForBlinds == WSC_SAC_ScheduledSlatAngle) THEN
        !    Blind(SurfaceWindow(SurfNum)%BlindNumber)%SlatAngle = SchSlatAngle
        !  ENDIF
        !ENDIF

      ENDIF

    END DO  ! End of surface loop

    ! Warning if a WindowShadingControl is not referenced by any window; user may think
    ! window shading is occurring when it really isn't
    DO ShadingCtrl = 1,TotWinShadingControl
      WinShadingCtrlReferenced = .FALSE.
      DO SurfNum = 1,TotSurfaces
        IF(Surface(SurfNum)%WindowShadingControlPtr == ShadingCtrl) WinShadingCtrlReferenced = .TRUE.
      END DO
      IF(.NOT.WinShadingCtrlReferenced) THEN
        CALL ShowWarningError(RoutineName//'WindowProperty:ShadingControl: "'//TRIM(WindowShadingControl(ShadingCtrl)%Name)// &
                    '" is not referenced by any window.')
      END IF
    END DO
  ENDIF

  ! Check for zones with not enough surfaces
  DO ZoneNum = 1,NumOfZones
    OpaqueHTSurfs = 0
    OpaqueHTSurfsWithWin = 0
    InternalMassSurfs = 0
    IF (Zone(ZoneNum)%SurfaceFirst == 0) CYCLE  ! Zone with no surfaces
    DO SurfNum = Zone(ZoneNum)%SurfaceFirst,Zone(ZoneNum)%SurfaceLast
      IF(Surface(SurfNum)%Class == SurfaceClass_Floor .OR. Surface(SurfNum)%Class == SurfaceClass_Wall .OR. &
         Surface(SurfNum)%Class == SurfaceClass_Roof) OpaqueHTSurfs = OpaqueHTSurfs + 1
      IF(Surface(SurfNum)%Class == SurfaceClass_IntMass) InternalMassSurfs = InternalMassSurfs + 1
      IF(Surface(SurfNum)%Class == SurfaceClass_Window) THEN
         ! Count base surface only once for multiple windows on a wall
         IF(SurfNum > 1 .AND. Surface(SurfNum-1)%Class /= SurfaceClass_Window) &
           OpaqueHTSurfsWithWin = OpaqueHTSurfsWithWin + 1
      END IF
    END DO
    IF(OpaqueHTSurfsWithWin == 1 .AND. OpaqueHTSurfs == 1 .AND. InternalMassSurfs == 0) THEN
      SurfError = .true.
      CALL ShowSevereError(RoutineName//'Zone '//Trim(Zone(ZoneNum)%Name)// &
        ' has only one floor, wall or roof, and this surface has a window.')
      CALL ShowContinueError('Add more floors, walls or roofs, or an internal mass surface.')
    END IF
    IF((OpaqueHTSurfs + InternalMassSurfs) < 6) THEN
      CALL ShowWarningError(RoutineName//'The total number of floors, walls, roofs and internal mass surfaces in Zone '// &
                            Trim(Zone(ZoneNum)%Name))
      CALL ShowContinueError('is < 6. This may cause an inaccurate zone heat balance calculation.')
    END IF
  END DO

    ! set up vertex of centroid for each surface.
  CALL CalcSurfaceCentroid

  CALL SetupShadeSurfacesForSolarCalcs  ! if shading surfaces are solar collectors or PV, then we need full solar calc.

  LayNumOutside=0
  DO SurfNum=1,TotSurfaces
    ! Check for EcoRoof and only 1 allowed to be used.
    IF (.not. Surface(SurfNum)%ExtEcoRoof) CYCLE
    IF (LayNumOutSide == 0) THEN
      LayNumOutSide=Construct(Surface(SurfNum)%Construction)%LayerPoint(1)
      CYCLE
    ENDIF
    IF (LayNumOutSide /= Construct(Surface(SurfNum)%Construction)%LayerPoint(1)) THEN
      CALL ShowSevereError(RoutineName//'Only one EcoRoof Material is currently allowed for all constructions.')
      CALL ShowContinueError('... first material='//TRIM(Material(LayNumOutSide)%Name))
      CALL ShowContinueError('... conflicting Construction='//TRIM(Construct(Surface(SurfNum)%Construction)%Name)//  &
                    ' uses material='//TRIM(Material(Construct(Surface(SurfNum)%Construction)%LayerPoint(1))%Name))
      ErrorsFound=.true.
    ENDIF
  ENDDO

  ! Set flag that determines whether a surface can be an exterior obstruction
  DO SurfNum = 1,TotSurfaces
    Surface(SurfNum)%ShadowSurfPossibleObstruction = .FALSE.
    ! Exclude non-exterior heat transfer surfaces (but not OtherSideCondModeledExt = -4 CR7640)
    IF(Surface(SurfNum)%HeatTransSurf .AND. Surface(SurfNum)%ExtBoundCond > 0 ) CYCLE
    IF(Surface(SurfNum)%HeatTransSurf .AND. Surface(SurfNum)%ExtBoundCond == Ground) CYCLE
    IF(Surface(SurfNum)%HeatTransSurf .AND. Surface(SurfNum)%ExtBoundCond == OtherSideCoefNoCalcExt) CYCLE
    IF(Surface(SurfNum)%HeatTransSurf .AND. Surface(SurfNum)%ExtBoundCond == OtherSideCoefCalcExt) CYCLE
    ! Exclude windows and doors, i.e., consider only their base surfaces as possible obstructions
    IF(Surface(SurfNum)%Class == SurfaceClass_Window .OR. Surface(SurfNum)%Class == SurfaceClass_Door) CYCLE
    ! Exclude duplicate shading surfaces
    ! TH 3/25/2010 CR 7872
    !  Shading surface names can start with Mir, a better way to use another flag
    !   to indicate whether a surface is a mirrored one.
    !IF(Surface(SurfNum)%Name(1:3) == 'Mir') CYCLE
    IF(Surface(SurfNum)%MirroredSurf) CYCLE

    Surface(SurfNum)%ShadowSurfPossibleObstruction = .TRUE.
  END DO

  ! Check for IRT surfaces in invalid places.
  iTmp1=0
  IF (ANY(Construct%TypeIsIRT)) THEN
    DO SurfNum = 1,TotSurfaces
      IF (.not. Surface(SurfNum)%HeatTransSurf) CYCLE  ! ignore shading surfaces
      IF (Surface(SurfNum)%ExtBoundCond > 0 .and. Surface(SurfNum)%ExtBoundCond /= SurfNum) CYCLE ! interzone, not adiabatic surface
      IF (.not. Construct(Surface(SurfNum)%Construction)%TypeIsIRT) CYCLE
      IF (.not. DisplayExtraWarnings) THEN
        iTmp1=iTmp1+1
      ELSE
        CALL ShowWarningError(RoutineName//'Surface="'//trim(Surface(SurfNum)%Name)//'" uses InfraredTransparent'//  &
           ' construction in a non-interzone surface. (illegal use)')
      ENDIF
    ENDDO
    IF (iTmp1 > 0) THEN
      CALL ShowWarningError(RoutineName//'Surfaces use InfraredTransparent constructions '//trim(TrimSigDigits(iTmp1))//  &
         ' in non-interzone surfaces. (illegal use)')
      CALL ShowContinueError('For explicit details on each use, use Output:Diagnostics,DisplayExtraWarnings;')
    ENDIF
  ENDIF

! Note, could do same for Window Area and detecting if Interzone Surface in Zone

  IF (Warning1Count > 0) THEN
    CALL ShowWarningMessage(RoutineName//'Window dimensions differ from Window 5/6 data file dimensions, '//  &
          trim(TrimSigDigits(Warning1Count))//' times.')
    CALL ShowContinueError('This will affect the frame heat transfer calculation if the frame in the Data File entry')
    CALL ShowContinueError('is not uniform, i.e., has sections with different geometry and/or thermal properties.')
    CALL ShowContinueError('For explicit details on each window, use Output:Diagnostics,DisplayExtraWarnings;')
  ENDIF
  IF (Warning2Count > 0) THEN
    CALL ShowWarningMessage(RoutineName//'Exterior Windows have been replaced with Window 5/6 two glazing systems, '//  &
          trim(TrimSigDigits(Warning2Count))//' times.')
    CALL ShowContinueError('Note that originally entered dimensions are overridden.')
    CALL ShowContinueError('For explicit details on each window, use Output:Diagnostics,DisplayExtraWarnings;')
  ENDIF
  IF (Warning3Count > 0) THEN
    CALL ShowWarningMessage(RoutineName//'Interior Windows have been replaced with Window 5/6 two glazing systems, '//  &
          trim(TrimSigDigits(Warning3Count))//' times.')
    CALL ShowContinueError('Note that originally entered dimensions are overridden.')
    CALL ShowContinueError('For explicit details on each window, use Output:Diagnostics,DisplayExtraWarnings;')
  ENDIF

  IF (TotalMultipliedWindows > 0) THEN
    CALL ShowWarningMessage(RoutineName//'There are '//trim(TrimSigDigits(TotalMultipliedWindows))//' window/glass door(s) '//  &
            'that may cause inaccurate shadowing due to Solar Distribution.')
    CALL ShowContinueError('For explicit details on each window, use Output:Diagnostics,DisplayExtraWarnings;')
    TotalWarningErrors=TotalWarningErrors+TotalMultipliedWindows
  ENDIF
  IF (TotalCoincidentVertices > 0) THEN
    CALL ShowWarningMessage(RoutineName//'There are '//trim(TrimSigDigits(TotalCoincidentVertices))//  &
       ' coincident/collinear vertices; These have been deleted unless the deletion would bring the number of surface sides < 3.')
    CALL ShowContinueError('For explicit details on each problem surface, use Output:Diagnostics,DisplayExtraWarnings;')
    TotalWarningErrors=TotalWarningErrors+TotalCoincidentVertices
  ENDIF
  IF (TotalDegenerateSurfaces > 0) THEN
    CALL ShowSevereMessage(RoutineName//'There are '//trim(TrimSigDigits(TotalDegenerateSurfaces))//  &
       ' degenerate surfaces; Degenerate surfaces are those with number of sides < 3.')
    CALL ShowContinueError('These surfaces should be deleted.')
    CALL ShowContinueError('For explicit details on each problem surface, use Output:Diagnostics,DisplayExtraWarnings;')
    TotalSevereErrors=TotalSevereErrors+TotalDegenerateSurfaces
  ENDIF

 CALL GetHTSurfExtVentedCavityData(ErrorsFound)

 CALL GetSurfaceHeatTransferAlgorithmOverrides(ErrorsFound)

 IF (SurfError .or. ErrorsFound) THEN
   ErrorsFound=.true.
   CALL ShowFatalError(RoutineName//'Errors discovered, program terminates.')
 ENDIF

 RETURN

END SUBROUTINE GetSurfaceData

SUBROUTINE GetGeometryParameters(ErrorsFound)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Linda Lawrie
          !       DATE WRITTEN   May 2000
          !       MODIFIED       na
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! This subroutine reads in the "Surface Geometry" parameters, verifies them,
          ! and sets "global" variables that will tell other routines how the surface
          ! vertices are expected in input.

          ! METHODOLOGY EMPLOYED:
          ! na

          ! REFERENCES:
          ! GlobalGeometryRules Definition
          !GlobalGeometryRules,
          !      \required-object
          !      \unique-object
          !  A1, \field Starting Vertex Position
          !      \required-field
          !      \note Specified as entry for a 4 sided surface/rectangle
          !      \note Surfaces are specified as viewed from outside the surface
          !      \note Shading surfaces as viewed from behind.  (towards what they are shading)
          !      \type choice
          !      \key UpperLeftCorner
          !      \key LowerLeftCorner
          !      \key UpperRightCorner
          !      \key LowerRightCorner
          !  A2, \field Vertex Entry Direction
          !      \required-field
          !      \type choice
          !      \key Counterclockwise
          !      \key Clockwise
          !  A3, \field Coordinate System
          !      \required-field
          !      \note relative -- coordinates are entered relative to zone origin
          !      \note world -- all coordinates entered are "absolute" for this facility
          !      \note absolute -- same as world
          !      \type choice
          !      \key Relative
          !      \key World
          !      \key Absolute
          !  A4, \field Daylighting Reference Point Coordinate System
          !      \type choice
          !      \key Relative
          !      \default Relative
          !      \note Relative -- coordinates are entered relative to zone origin
          !      \key World
          !      \note World -- all coordinates entered are "absolute" for this facility
          !      \key Absolute
          !      \note absolute -- same as world
          !  A5; \field Rectangular Surface Coordinate System
          !      \type choice
          !      \key Relative
          !      \default Relative
          !      \note Relative -- Starting corner is entered relative to zone origin
          !      \key World
          !      \note World -- Starting corner is entered in "absolute"
          !      \key Absolute
          !      \note absolute -- same as world

          ! USE STATEMENTS:
  USE DataIPShortCuts
  USE InputProcessor, ONLY: GetNumObjectsFound, GetObjectItem, FindItem, SameString, VerifyName

  IMPLICIT NONE    ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
  LOGICAL, INTENT(INOUT)  :: ErrorsFound  ! set to true if errors found during input

          ! SUBROUTINE PARAMETER DEFINITIONS:
  CHARACTER(len=3), PARAMETER, DIMENSION(4)  :: AbCorners=(/'ULC','LLC','LRC','URC'/)
  CHARACTER(len=16), PARAMETER, DIMENSION(4) :: FlCorners=(/'UpperLeftCorner ','LowerLeftCorner ',  &
                                                            'LowerRightCorner','UpperRightCorner'/)

          ! INTERFACE BLOCK SPECIFICATIONS
          ! na

          ! DERIVED TYPE DEFINITIONS
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
  INTEGER NumStmt
  CHARACTER(len=MaxNameLength), DIMENSION(5) :: GAlphas
  INTEGER NAlphas
  REAL(r64), DIMENSION(1) :: GNum
  INTEGER NNum
  INTEGER IOSTAT
  LOGICAL OK
  INTEGER Found
  CHARACTER(len=150) :: OutMsg

  cCurrentModuleObject='GlobalGeometryRules'
  NumStmt=GetNumObjectsFound(cCurrentModuleObject)
  OutMsg=' Surface Geometry,'

  SELECT CASE(NumStmt)

  CASE (1)
    ! This is the valid case
    CALL GetObjectItem(cCurrentModuleObject,1,GAlphas,NAlphas,GNum,NNum,IOSTAT,  &
                   AlphaBlank=lAlphaFieldBlanks,NumBlank=lNumericFieldBlanks,  &
                   AlphaFieldnames=cAlphaFieldNames,NumericFieldNames=cNumericFieldNames)

    ! Even though these will be validated, set defaults in case error here -- wont
    ! cause aborts in later surface gets (hopefully)
    Corner=UpperLeftCorner
    WorldCoordSystem=.true.
    CCW=.true.

    OK=.false.
    Found=FindItem(GAlphas(1),AbCorners,4)
    IF (Found == 0) THEN
      Found=FindItem(GAlphas(1),FlCorners,4)
      IF (Found == 0) THEN
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//': Invalid '//TRIM(cAlphaFieldNames(1))//'='//TRIM(GAlphas(1)))
        ErrorsFound=.true.
      ELSE
        Corner=Found
        OK=.true.
        OutMsg=TRIM(OutMsg)//TRIM(FLCorners(Corner))//','
      ENDIF
    ELSE
      Corner=Found
      OutMsg=TRIM(OutMsg)//TRIM(FLCorners(Corner))//','
      OK=.true.
    ENDIF

    OK=.false.
    IF (SameString(GAlphas(2),'CCW') .or. SameString(GAlphas(2),'Counterclockwise')) THEN
      CCW=.true.
      OutMsg=TRIM(OutMsg)//'Counterclockwise'//','
      OK=.true.
    ENDIF
    IF (SameString(GAlphas(2),'CW')  .or. SameString(GAlphas(2),'Clockwise')) THEN
      CCW=.false.
      OutMsg=TRIM(OutMsg)//'Clockwise'//','
      OK=.true.
    ENDIF
    IF (.not. OK) THEN
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//': Invalid '//TRIM(cAlphaFieldNames(2))//'='//TRIM(GAlphas(2)))
      ErrorsFound=.true.
    ENDIF

    OK=.false.
    IF (SameString(GAlphas(3),'WCS') .or. SameString(GAlphas(3),'WorldCoordinateSystem') .or.   &
        SameString(GAlphas(3),'World') .or. SameString(GAlphas(3),'Absolute')) THEN
      WorldCoordSystem=.true.
      OutMsg=TRIM(OutMsg)//'WorldCoordinateSystem'//','
      OK=.true.
    ENDIF
    IF (SameString(GAlphas(3)(1:3),'Rel') .or. SameString(GAlphas(3)(1:8),'Relative') .or. SameString(GAlphas(3),'Local')) THEN
      WorldCoordSystem=.false.
      OutMsg=TRIM(OutMsg)//'RelativeCoordinateSystem'//','
      OK=.true.
    ENDIF
    IF (.not. OK) THEN
      CALL ShowWarningError(TRIM(cCurrentModuleObject)//': Invalid '//TRIM(cAlphaFieldNames(3))//'='//TRIM(GAlphas(3)))
      CALL ShowContinueError(TRIM(cAlphaFieldNames(3))//' defaults to "WorldCoordinateSystem"')
      WorldCoordSystem=.true.
      OutMsg=TRIM(OutMsg)//'WorldCoordinateSystem'//','
    ENDIF

    OK=.false.
    IF (SameString(GAlphas(4),'WCS') .or. SameString(GAlphas(4),'WorldCoordinateSystem') .or.   &
        SameString(GAlphas(4),'World') .or. SameString(GAlphas(4),'Absolute')) THEN
      DaylRefWorldCoordSystem=.true.
      OutMsg=TRIM(OutMsg)//'WorldCoordinateSystem'//','
      OK=.true.
    ENDIF
    IF (SameString(GAlphas(4)(1:3),'Rel') .or. SameString(GAlphas(4)(1:8),'Relative') .or.   &
        SameString(GAlphas(4),'Local') .or. GAlphas(4) == Blank) THEN
      DaylRefWorldCoordSystem=.false.
      OutMsg=TRIM(OutMsg)//'RelativeCoordinateSystem'//','
      OK=.true.
    ENDIF
    IF (.not. OK) THEN
      CALL ShowWarningError(TRIM(cCurrentModuleObject)//': Invalid '//TRIM(cAlphaFieldNames(4))//'='//TRIM(GAlphas(4)))
      CALL ShowContinueError(TRIM(cAlphaFieldNames(4))//' defaults to "RelativeToZoneOrigin"')
      DaylRefWorldCoordSystem=.false.
      OutMsg=TRIM(OutMsg)//'RelativeToZoneOrigin'//','
    ENDIF

    OK=.false.
    IF (SameString(GAlphas(5),'WCS') .or. SameString(GAlphas(5),'WorldCoordinateSystem') .or.   &
        SameString(GAlphas(5),'World') .or. SameString(GAlphas(5),'Absolute')) THEN
      RectSurfRefWorldCoordSystem=.true.
      OutMsg=TRIM(OutMsg)//'WorldCoordinateSystem'
      OK=.true.
    ENDIF
    IF (SameString(GAlphas(5)(1:3),'Rel') .or. SameString(GAlphas(5)(1:8),'Relative') .or.   &
        SameString(GAlphas(5),'Local') .or. GAlphas(5) == Blank) THEN
      RectSurfRefWorldCoordSystem=.false.
      OutMsg=TRIM(OutMsg)//'RelativeToZoneOrigin'
      OK=.true.
    ENDIF
    IF (.not. OK) THEN
      CALL ShowWarningError(TRIM(cCurrentModuleObject)//': Invalid '//TRIM(cAlphaFieldNames(5))//'='//TRIM(GAlphas(5)))
      CALL ShowContinueError(TRIM(cAlphaFieldNames(5))//' defaults to "RelativeToZoneOrigin"')
      RectSurfRefWorldCoordSystem=.false.
      OutMsg=TRIM(OutMsg)//'RelativeToZoneOrigin'
    ENDIF

  CASE (0)

    CALL ShowSevereError(TRIM(cCurrentModuleObject)//': Required object not found.')
    OutMsg=TRIM(OutMsg)//'None found in input'
    ErrorsFound=.true.

  CASE DEFAULT

    CALL ShowSevereError(TRIM(cCurrentModuleObject)//': Too many objects entered.  Only one allowed.')
    ErrorsFound=.true.

  END SELECT

  IF (.not. WorldCoordSystem) THEN
    IF (DaylRefWorldCoordSystem) THEN
      CALL ShowWarningError(trim(cCurrentModuleObject)//': Potential mismatch of coordinate specifications.')
      CALL ShowContinueError(trim(cAlphaFieldNames(3))//'="'//trim(GAlphas(3))//'"; while ')
      CALL ShowContinueError(trim(cAlphaFieldNames(4))//'="'//trim(GAlphas(4))//'".')
    ENDIF
    IF (RectSurfRefWorldCoordSystem) THEN
      CALL ShowWarningError(trim(cCurrentModuleObject)//': Potential mismatch of coordinate specifications.')
      CALL ShowContinueError(trim(cAlphaFieldNames(3))//'="'//trim(GAlphas(3))//'"; while ')
      CALL ShowContinueError(trim(cAlphaFieldNames(5))//'="'//trim(GAlphas(5))//'".')
    ENDIF
  ENDIF

  WRITE(OutputFileInits,720) '! <SurfaceGeometry>,Starting Corner,'//  &
              'Vertex Input Direction,Coordinate System,'//  &
              'Daylight Reference Point Coordinate System,'//'Rectangular (Simple) Surface Coordinate System'
  WRITE(OutputFileInits,720) TRIM(OutMsg)

720 Format(A)

  RETURN

END SUBROUTINE GetGeometryParameters

SUBROUTINE GetDetShdSurfaceData(ErrorsFound,SurfNum,TotDetachedFixed,TotDetachedBldg)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Linda Lawrie
          !       DATE WRITTEN   May 2000
          !       MODIFIED       na
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! This subroutine gets the Detached Shading Surface Data,
          ! checks it for errors, etc.

          ! METHODOLOGY EMPLOYED:
          ! na

          ! REFERENCES:
  ! Detached Shading Surface Definition(s)
  !Surface:Shading:Detached:Fixed,
  !       \memo used for shading elements such as trees
  !       \memo these items are fixed in space and would not move with relative geometry
  !  A1 , \field User Supplied Surface Name
  !       \required-field
  !       \type alpha
  !  A2,  \field TransSchedShadowSurf
  !       \note Transmittance schedule for the shading device, defaults to zero (always opaque)
  !       \type object-list
  !       \object-list ScheduleNames
  !  N1 , \field Number of Surface Vertex Groups -- Number of (X,Y,Z) groups in this surface
  !       \required-field
  !       \note shown with 12 vertex coordinates -- extensible object
  !       \autocalculatable
  !       \default autocalculate
  !       \minimum 3
  !       \note Rules for vertices are given in SurfaceGeometry coordinates --
  !       \note For this object all surface coordinates are relative to the building origin (0,0,0)
  !       \note and will rotate with the BUILDING north axis.
  !  N2,  \field Vertex 1 X-coordinate
  !       \units m
  !       \type real
  !  N3-37; as indicated by the N1 value
  !
  !Surface:Shading:Detached:Building,
  !       \memo used for shading elements such as trees, other buildings, parts of this building not being modeled
  !       \memo these items are relative to the current building and would move with relative geometry
  !  A1 , \field User Supplied Surface Name
  !       \required-field
  !       \type alpha
  !  A2,  \field TransSchedShadowSurf
  !       \note Transmittance schedule for the shading device, defaults to zero (always opaque)
  !       \type object-list
  !       \object-list ScheduleNames
  !  N1 , \field Number of Surface Vertex Groups -- Number of (X,Y,Z) groups in this surface
  !       \required-field
  !       \note shown with 12 vertex coordinates -- extensible object
  !       \autocalculatable
  !       \default autocalculate
  !       \minimum 3
  !       \note Rules for vertices are given in SurfaceGeometry coordinates --
  !       \note For this object all surface coordinates are relative to the building origin (0,0,0)
  !       \note and will rotate with the BUILDING north axis.
  !  N2,  \field Vertex 1 X-coordinate
  !       \units m
  !       \type real
  !  N3-37; as indicated by the N1 value

          ! USE STATEMENTS:
  USE DataIPShortCuts
  USE DataReportingFlags
  USE InputProcessor, ONLY: GetNumObjectsFound, GetObjectItem, VerifyName, GetObjectDefMaxArgs
  USE ScheduleManager, ONLY: GetScheduleIndex,CheckScheduleValueMinMax,GetScheduleMinValue,GetScheduleMaxValue
  USE General, ONLY: TrimSigDigits

  IMPLICIT NONE    ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
  LOGICAL, INTENT(INOUT)    :: ErrorsFound       ! Error flag indicator (true if errors found)
  INTEGER, INTENT(INOUT)    :: SurfNum           ! Count of Current SurfaceNumber
  INTEGER, INTENT(IN)       :: TotDetachedFixed  ! Number of Fixed Detached Shading Surfaces to obtain
  INTEGER, INTENT(IN)       :: TotDetachedBldg   ! Number of Building Detached Shading Surfaces to obtain

          ! SUBROUTINE PARAMETER DEFINITIONS:
  CHARACTER(len=*), PARAMETER, DIMENSION(2) :: cModuleObjects=  &
    (/'Shading:Site:Detailed    ',  &
      'Shading:Building:Detailed'/)

          ! INTERFACE BLOCK SPECIFICATIONS
          ! na

          ! DERIVED TYPE DEFINITIONS
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
  INTEGER :: IOStat            ! IO Status when calling get input subroutine
  INTEGER :: NumAlphas   ! Number of material alpha names being passed
  INTEGER :: NumNumbers    ! Number of material properties being passed
  INTEGER :: Loop
  LOGICAL :: ErrorInName
  LOGICAL :: IsBlank
  INTEGER :: Item
  INTEGER :: ItemsToGet
  INTEGER :: ClassItem
  INTEGER :: numSides
  REAL(r64) :: SchedMinValue
  REAL(r64) :: SchedMaxValue

  IF ((TotDetachedFixed+TotDetachedBldg) > 0 .and. SolarDistribution == MinimalShadowing) THEN
    CALL ShowWarningError('Detached shading effects are ignored when Solar Distribution = MinimalShadowing')
  ENDIF

  IF ((TotDetachedFixed+TotDetachedBldg) == 0) RETURN

  DO Item=1,2

    cCurrentModuleObject=cModuleObjects(Item)
    IF (Item == 1) THEN
      ItemsToGet=TotDetachedFixed
      ClassItem=SurfaceClass_Detached_F
    ELSE  !IF (Item == 2) THEN
      ItemsToGet=TotDetachedBldg
      ClassItem=SurfaceClass_Detached_B
    ENDIF

    CALL GetObjectDefMaxArgs(cCurrentModuleObject,Loop,NumAlphas,NumNumbers)
    IF (NumAlphas /= 2) THEN
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//': Object Definition indicates'// &
                           'not = 2 Alpha Objects, Number Indicated='//  &
                           TRIM(TrimSigDigits(NumAlphas)))
      ErrorsFound=.true.
    ENDIF

    DO Loop=1,ItemsToGet
      CALL GetObjectItem(cCurrentModuleObject,Loop,cAlphaArgs,NumAlphas, &
                         rNumericArgs,NumNumbers,IOSTAT,  &
                         AlphaBlank=lAlphaFieldBlanks,NumBlank=lNumericFieldBlanks,  &
                         AlphaFieldnames=cAlphaFieldNames,NumericFieldNames=cNumericFieldNames)
      ErrorInName=.false.
      IsBlank=.false.
      CALL VerifyName(cAlphaArgs(1),SurfaceTmp%Name,SurfNum,ErrorInName,IsBlank,TRIM(cCurrentModuleObject)//' Name')
      IF (ErrorInName) THEN
        CALL ShowContinueError('...each surface name must not duplicate other surface names (of any type)')
        ErrorsFound=.true.
        CYCLE
      ENDIF

      SurfNum=SurfNum+1
      SurfaceTmp(SurfNum)%Name = cAlphaArgs(1)  ! Set the Surface Name in the Derived Type
      SurfaceTmp(SurfNum)%Class=ClassItem
      SurfaceTmp(SurfNum)%HeatTransSurf=.false.
    ! Base transmittance of a shadowing (sub)surface
      IF (.not. lAlphaFieldBlanks(2)) THEN
         ! Schedule for a shadowing (sub)surface
        SurfaceTmp(SurfNum)%SchedShadowSurfIndex = GetScheduleIndex(cAlphaArgs(2))
        IF (SurfaceTmp(SurfNum)%SchedShadowSurfIndex == 0) THEN
          CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                               '", '//TRIM(cAlphaFieldNames(2))//' not found='//TRIM(cAlphaArgs(2)))
          ErrorsFound=.true.
        ENDIF
      ELSE
        SurfaceTmp(SurfNum)%SchedShadowSurfIndex=0
      ENDIF
      IF (SurfaceTmp(SurfNum)%SchedShadowSurfIndex /= 0) THEN
        IF (.not. CheckScheduleValueMinMax(SurfaceTmp(SurfNum)%SchedShadowSurfIndex,'>=',0.0d0,'<=',1.0d0)) THEN
          CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                               '", '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))// &
                               '", values not in range [0,1].')
          ErrorsFound=.true.
        ENDIF
        SchedMinValue=GetScheduleMinValue(SurfaceTmp(SurfNum)%SchedShadowSurfIndex)
        SurfaceTmp(SurfNum)%SchedMinValue=SchedMinValue
        SchedMaxValue=GetScheduleMaxValue(SurfaceTmp(SurfNum)%SchedShadowSurfIndex)
        IF (SchedMinValue == 1.0d0) THEN
          CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                               '", '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))// &
                               '", is always transparent.')
          SurfaceTmp(SurfNum)%IsTransparent=.true.
        ENDIF
        IF (SchedMinValue < 0.0d0) THEN
          CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                               '", '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))// &
                               '", has schedule values < 0.')
          CALL ShowContinueError('...Schedule values < 0 have no meaning for shading elements.')
        ENDIF
        IF (SchedMaxValue > 1.0d0) THEN
          CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                               '", '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))// &
                               '", has schedule values > 1.')
          CALL ShowContinueError('...Schedule values > 1 have no meaning for shading elements.')
        ENDIF
        IF (ABS(SchedMinValue-SchedMaxValue) > 1.0d-6) THEN
          SurfaceTmp(SurfNum)%ShadowSurfSchedVaries=.true.
          ShadingTransmittanceVaries=.true.
        ENDIF
      ENDIF
      IF (lNumericFieldBlanks(1) .or. rNumericArgs(1) == AutoCalculate) THEN
        numSides=(NumNumbers-1)/3
        SurfaceTmp(SurfNum)%Sides=numSides
        IF (MOD(NumNumbers-1,3) /= 0) THEN
          CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                          '", '//TRIM(cNumericFieldNames(1))//          &
                          ' not even multiple of 3. Will read in '//   &
                          TRIM(TrimSigDigits(SurfaceTmp(SurfNum)%Sides)))
        ENDIF
        IF (numSides < 3) THEN
          CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                          '", '//TRIM(cNumericFieldNames(1))//' (autocalculate) must be >= 3. Only '//  &
                          TRIM(TrimSigDigits(SurfaceTmp(SurfNum)%Sides))//' provided.')
          ErrorsFound=.true.
          CYCLE
        ENDIF
      ELSE
        numSides=(NumNumbers-1)/3
        SurfaceTmp(SurfNum)%Sides=rNumericArgs(1)
        IF (numSides > SurfaceTmp(SurfNum)%Sides) THEN
          CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                          '", field '//TRIM(cNumericFieldNames(1))//'='//TRIM(TrimSigDigits(SurfaceTmp(SurfNum)%Sides)))
          CALL ShowContinueError('...but '//TRIM(TrimSigDigits(numSides))//' were entered. Only the indicated '//  &
                          TRIM(cNumericFieldNames(1))//' will be used.')
        ENDIF
      ENDIF
      ALLOCATE(SurfaceTmp(SurfNum)%Vertex(SurfaceTmp(SurfNum)%Sides))
      CALL GetVertices(SurfNum,SurfaceTmp(SurfNum)%Sides,rNumericArgs(2:))
      CALL CheckConvexity(SurfNum,SurfaceTmp(SurfNum)%Sides)
      IF (MakeMirroredDetachedShading) THEN
        CALL MakeMirrorSurface(SurfNum)
      ENDIF
    ENDDO

  ENDDO ! Item Loop

  RETURN

END SUBROUTINE GetDetShdSurfaceData

SUBROUTINE GetRectDetShdSurfaceData(ErrorsFound,SurfNum,TotRectDetachedFixed,TotRectDetachedBldg)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Linda Lawrie
          !       DATE WRITTEN   January 2009
          !       MODIFIED       na
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! Gets the simple, rectantular detached surfaces.

          ! METHODOLOGY EMPLOYED:
          ! na

          ! REFERENCES:
          ! na

          ! USE STATEMENTS:
  USE DataIPShortCuts
  USE DataReportingFlags
  USE InputProcessor, ONLY: GetNumObjectsFound, GetObjectItem, VerifyName, GetObjectDefMaxArgs
  USE General, ONLY: TrimSigDigits

  IMPLICIT NONE    ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
  LOGICAL, INTENT(INOUT)    :: ErrorsFound       ! Error flag indicator (true if errors found)
  INTEGER, INTENT(INOUT)    :: SurfNum           ! Count of Current SurfaceNumber
  INTEGER, INTENT(IN)       :: TotRectDetachedFixed  ! Number of Fixed Detached Shading Surfaces to obtain
  INTEGER, INTENT(IN)       :: TotRectDetachedBldg   ! Number of Building Detached Shading Surfaces to obtain

          ! SUBROUTINE PARAMETER DEFINITIONS:
  CHARACTER(len=*), PARAMETER, DIMENSION(2) :: cModuleObjects=  &
    (/'Shading:Site    ',  &
      'Shading:Building'/)

          ! INTERFACE BLOCK SPECIFICATIONS
          ! na

          ! DERIVED TYPE DEFINITIONS
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
  INTEGER :: IOStat            ! IO Status when calling get input subroutine
  INTEGER :: NumAlphas   ! Number of material alpha names being passed
  INTEGER :: NumNumbers    ! Number of material properties being passed
  INTEGER :: Loop
  LOGICAL :: ErrorInName
  LOGICAL :: IsBlank
  INTEGER :: Item
  INTEGER :: ItemsToGet
  INTEGER :: ClassItem

  IF ((TotRectDetachedFixed+TotRectDetachedBldg) > 0 .and. SolarDistribution == MinimalShadowing) THEN
    CALL ShowWarningError('Detached shading effects are ignored when Solar Distribution = MinimalShadowing')
  ENDIF

  IF (TotRectDetachedFixed+TotRectDetachedBldg == 0) RETURN

  DO Item=1,2

    cCurrentModuleObject=cModuleObjects(Item)
    IF (Item == 1) THEN
      ItemsToGet=TotRectDetachedFixed
      ClassItem=SurfaceClass_Detached_F
    ELSE  !IF (Item == 2) THEN
      ItemsToGet=TotRectDetachedBldg
      ClassItem=SurfaceClass_Detached_B
    ENDIF

    CALL GetObjectDefMaxArgs(cCurrentModuleObject,Loop,NumAlphas,NumNumbers)
    IF (NumAlphas /= 1) THEN
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//': Object Definition indicates'// &
                           'not = 1 Alpha Objects, Number Indicated='//  &
                           TRIM(TrimSigDigits(NumAlphas)))
      ErrorsFound=.true.
    ENDIF

    DO Loop=1,ItemsToGet
      CALL GetObjectItem(cCurrentModuleObject,Loop,cAlphaArgs,NumAlphas, &
                         rNumericArgs,NumNumbers,IOSTAT,  &
                         AlphaBlank=lAlphaFieldBlanks,NumBlank=lNumericFieldBlanks,  &
                         AlphaFieldnames=cAlphaFieldNames,NumericFieldNames=cNumericFieldNames)
      ErrorInName=.false.
      IsBlank=.false.
      CALL VerifyName(cAlphaArgs(1),SurfaceTmp%Name,SurfNum,ErrorInName,IsBlank,TRIM(cCurrentModuleObject)//' Name')
      IF (ErrorInName) THEN
        CALL ShowContinueError('...each surface name must not duplicate other surface names (of any type)')
        ErrorsFound=.true.
        CYCLE
      ENDIF

      SurfNum=SurfNum+1
      SurfaceTmp(SurfNum)%Name = cAlphaArgs(1)  ! Set the Surface Name in the Derived Type
      SurfaceTmp(SurfNum)%Class=ClassItem
      SurfaceTmp(SurfNum)%HeatTransSurf=.false.

      SurfaceTmp(SurfNum)%Azimuth=rNumericArgs(1)
      IF (SurfaceTmp(SurfNum)%Class == SurfaceClass_Detached_B .and. .not. WorldCoordSystem) THEN
        SurfaceTmp(SurfNum)%Azimuth=SurfaceTmp(SurfNum)%Azimuth+BuildingAzimuth
      ENDIF
      IF (SurfaceTmp(SurfNum)%Class == SurfaceClass_Detached_B) THEN
        SurfaceTmp(SurfNum)%Azimuth=SurfaceTmp(SurfNum)%Azimuth+BuildingRotationAppendixG
      ENDIF
      SurfaceTmp(SurfNum)%Tilt=rNumericArgs(2)

      SurfaceTmp(SurfNum)%Sides=4
      ALLOCATE(SurfaceTmp(SurfNum)%Vertex(SurfaceTmp(SurfNum)%Sides))

      CALL MakeRectangularVertices(SurfNum,rNumericArgs(3),  &
                                   rNumericArgs(4),rNumericArgs(5),rNumericArgs(6),rNumericArgs(7),RectSurfRefWorldCoordSystem)

      IF (SurfaceTmp(SurfNum)%Area <= 0.0d0) THEN
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
              '", Surface Area <= 0.0; Entered Area='//  &
              TRIM(TrimSigDigits(SurfaceTmp(SurfNum)%Area,2)))
        ErrorsFound=.true.
      ENDIF

      IF (MakeMirroredDetachedShading) THEN
        CALL MakeMirrorSurface(SurfNum)
      ENDIF
    ENDDO

  ENDDO ! Item Loop

  RETURN

END SUBROUTINE GetRectDetShdSurfaceData

SUBROUTINE GetHTSurfaceData(ErrorsFound,SurfNum,TotHTSurfs,TotDetailedWalls,TotDetailedRoofs,TotDetailedFloors,  &
                  BaseSurfCls,BaseSurfIDs,NeedToAddSurfaces)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Linda Lawrie
          !       DATE WRITTEN   May 2000
          !       MODIFIED       na
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! This subroutine gets the HeatTransfer Surface Data,
          ! checks it for errors, etc.

          ! METHODOLOGY EMPLOYED:
          ! na

          ! REFERENCES:
  ! Heat Transfer Surface Definition
  !BuildingSurface:Detailed,
  !  \extensible:3 -- duplicate last set of x,y,z coordinates (last 3 fields), remembering to remove ; from "inner" fields.
  !  \format vertices
  !  A1 , \field Name
  !       \required-field
  !       \type alpha
  !       \reference SurfaceNames
  !       \reference SurfAndSubSurfNames
  !       \reference AllHeatTranSurfNames
  !       \reference HeatTranBaseSurfNames
  !       \reference OutFaceEnvNames
  !       \reference AllHeatTranAngFacNames
  !       \reference RadGroupAndSurfNames
  !       \reference SurfGroupAndHTSurfNames
  !       \reference AllShadingAndHTSurfNames
  !  A2 , \field Surface Type
  !       \required-field
  !       \type choice
  !       \key Floor
  !       \key Wall
  !       \key Ceiling
  !       \key Roof
  !  A3 , \field Construction Name
  !       \required-field
  !       \note To be matched with a construction in this input file
  !       \type object-list
  !       \object-list ConstructionNames
  !  A4 , \field Zone Name
  !       \required-field
  !       \note Zone the surface is a part of
  !       \type object-list
  !       \object-list ZoneNames
  !  A5 , \field Outside Boundary Condition
  !       \required-field
  !       \type choice
  !       \key Adiabatic
  !       \key Surface
  !       \key Zone
  !       \key Outdoors
  !       \key Ground
  !       \key GroundFCfactorMethod
  !       \key OtherSideCoefficients
  !       \key OtherSideConditionsModel
  !       \key GroundSlabPreprocessorAverage
  !       \key GroundSlabPreprocessorCore
  !       \key GroundSlabPreprocessorPerimeter
  !       \key GroundBasementPreprocessorAverageWall
  !       \key GroundBasementPreprocessorAverageFloor
  !       \key GroundBasementPreprocessorUpperWall
  !       \key GroundBasementPreprocessorLowerWall
  !  A6,  \field Outside Boundary Condition Object
  !       \type object-list
  !       \object-list OutFaceEnvNames
  !       \note Non-blank only if the field Outside Boundary Condition is Surface,
  !       \note Zone, OtherSideCoefficients or OtherSideConditionsModel
  !       \note If Surface, specify name of corresponding surface in adjacent zone or
  !       \note specify current surface name for internal partition separating like zones
  !       \note If Zone, specify the name of the corresponding zone and
  !       \note the program will generate the corresponding interzone surface
  !       \note If OtherSideCoefficients, specify name of SurfaceProperty:OtherSideCoefficients
  !       \note If OtherSideConditionsModel, specify name of SurfaceProperty:OtherSideConditionsModel
  !  A7 , \field Sun Exposure
  !       \required-field
  !       \type choice
  !       \key SunExposed
  !       \key NoSun
  !       \default SunExposed
  !  A8,  \field Wind Exposure
  !       \required-field
  !       \type choice
  !       \key WindExposed
  !       \key NoWind
  !       \default WindExposed
  !  N1,  \field View Factor to Ground
  !       \type real
  !       \note From the exterior of the surface
  !       \note Unused if one uses the "reflections" options in Solar Distribution in Building input
  !       \note unless a DaylightingDevice:Shelf or DaylightingDevice:Tubular object has been specified.
  !       \note autocalculate will automatically calculate this value from the tilt of the surface
  !       \autocalculatable
  !       \minimum 0.0
  !       \maximum 1.0
  !       \default autocalculate
  !  N2 , \field Number of Vertices
  !       \note shown with 120 vertex coordinates -- extensible object
  !       \note  "extensible" -- duplicate last set of x,y,z coordinates (last 3 fields),
  !       \note remembering to remove ; from "inner" fields.
  !       \note for clarity in any error messages, renumber the fields as well.
  !       \note (and changing z terminator to a comma "," for all but last one which needs a semi-colon ";")
  !       \autocalculatable
  !       \minimum 3
  !       \default autocalculate
  !       \note vertices are given in GlobalGeometryRules coordinates -- if relative, all surface coordinates
  !       \note are "relative" to the Zone Origin.  If world, then building and zone origins are used
  !       \note for some internal calculations, but all coordinates are given in an "absolute" system.
  !  N3-xx as indicated by the N3 value

          ! USE STATEMENTS:
  USE DataIPShortCuts
  USE InputProcessor, ONLY: GetNumObjectsFound, GetObjectItem, FindItemInList, VerifyName, SameString, GetObjectDefMaxArgs
  USE General, ONLY: RoundSigDigits,TrimSigDigits


  IMPLICIT NONE    ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
  LOGICAL, INTENT(INOUT)         :: ErrorsFound       ! Error flag indicator (true if errors found)
  INTEGER, INTENT(INOUT)         :: SurfNum           ! Count of Current SurfaceNumber
  INTEGER, INTENT(IN)            :: TotHTSurfs        ! Number of Heat Transfer Base Surfaces to obtain
  INTEGER, INTENT(IN)            :: TotDetailedWalls  ! Number of Wall:Detailed items to obtain
  INTEGER, INTENT(IN)            :: TotDetailedRoofs  ! Number of RoofCeiling:Detailed items to obtain
  INTEGER, INTENT(IN)            :: TotDetailedFloors ! Number of Floor:Detailed items to obtain
  CHARACTER(len=*), DIMENSION(:), INTENT(IN) :: BaseSurfCls  ! Valid Classes for Base Surfaces
  INTEGER, DIMENSION(:), INTENT(IN) :: BaseSurfIDs
  INTEGER, INTENT(OUT)           :: NeedToAddSurfaces ! Number of surfaces to add, based on unentered IZ surfaces

          ! SUBROUTINE PARAMETER DEFINITIONS:
  CHARACTER(len=*), PARAMETER, DIMENSION(4) :: cModuleObjects=  &
    (/'BuildingSurface:Detailed',  &
      'Wall:Detailed           ',  &
      'Floor:Detailed          ',  &
      'RoofCeiling:Detailed    '/)

          ! INTERFACE BLOCK SPECIFICATIONS
          ! na

          ! DERIVED TYPE DEFINITIONS
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
  INTEGER :: IOStat            ! IO Status when calling get input subroutine
  INTEGER :: SurfaceNumAlpha   ! Number of material alpha names being passed
  INTEGER :: SurfaceNumProp    ! Number of material properties being passed
  INTEGER :: ZoneNum           ! DO loop counter (zones)
  INTEGER :: Found             ! For matching interzone surfaces
  INTEGER :: Loop
  LOGICAL :: ErrorInName
  LOGICAL :: IsBlank
  INTEGER :: Item
  INTEGER :: ItemsToGet
  INTEGER :: ClassItem
  INTEGER :: ArgPointer
  INTEGER :: numSides

  CALL GetOSCData(ErrorsFound)
  Call GetOSCMData(ErrorsFound)

  NeedToAddSurfaces=0

  DO Item=1,4

    cCurrentModuleObject=cModuleObjects(Item)
    IF (Item == 1) THEN
      ItemsToGet=TotHTSurfs
      ClassItem=0
    ELSEIF (Item == 2) THEN
      ItemsToGet=TotDetailedWalls
      ClassItem=1
    ELSEIF (Item == 3) THEN
      ItemsToGet=TotDetailedFloors
      ClassItem=2
    ELSE !IF (Item == 4) THEN
      ItemsToGet=TotDetailedRoofs
      ClassItem=3
    ENDIF

    CALL GetObjectDefMaxArgs(cCurrentModuleObject,Loop,SurfaceNumAlpha,SurfaceNumProp)
    IF (Item == 1) THEN
      IF (SurfaceNumAlpha /= 8) THEN
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//': Object Definition indicates '// &
                             'not = 8 Alpha Objects, Number Indicated='//  &
                             TRIM(TrimSigDigits(SurfaceNumAlpha)))
        ErrorsFound=.true.
      ENDIF
    ELSE
      IF (SurfaceNumAlpha /= 7) THEN
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//': Object Definition indicates '// &
                             'not = 7 Alpha Objects, Number Indicated='//  &
                             TRIM(TrimSigDigits(SurfaceNumAlpha)))
        ErrorsFound=.true.
      ENDIF
    ENDIF

    DO Loop=1,ItemsToGet
      CALL GetObjectItem(cCurrentModuleObject,Loop,cAlphaArgs,SurfaceNumAlpha,rNumericArgs,SurfaceNumProp,IOSTAT,  &
                     AlphaBlank=lAlphaFieldBlanks,NumBlank=lNumericFieldBlanks,  &
                     AlphaFieldnames=cAlphaFieldNames,NumericFieldNames=cNumericFieldNames)
      ErrorInName=.false.
      IsBlank=.false.
      CALL VerifyName(cAlphaArgs(1),SurfaceTmp%Name,SurfNum,ErrorInName,IsBlank,TRIM(cCurrentModuleObject)//' Name')
      IF (ErrorInName) THEN
        CALL ShowContinueError('...each surface name must not duplicate other surface names (of any type)')
        ErrorsFound=.true.
        CYCLE
      ENDIF

      SurfNum=SurfNum+1
      SurfaceTmp(SurfNum)%Name = cAlphaArgs(1)  ! Set the Surface Name in the Derived Type
      ArgPointer=2
      IF (Item == 1) THEN
        IF (cAlphaArgs(2) == 'CEILING') cAlphaArgs(2)='ROOF'
        ClassItem=FindItemInList(cAlphaArgs(2),BaseSurfCls,3)
        IF (ClassItem == 0) THEN
          CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                                 '", invalid '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2)))
          ErrorsFound=.true.
        ELSE
          SurfaceTmp(SurfNum)%Class = BaseSurfIDs(ClassItem)
        ENDIF
        ArgPointer=ArgPointer+1
      ELSE
        SurfaceTmp(SurfNum)%Class = BaseSurfIDs(ClassItem)
      ENDIF

      SurfaceTmp(SurfNum)%Construction=FindIteminList(cAlphaArgs(ArgPointer),Construct%Name,TotConstructs)

      IF(SurfaceTmp(SurfNum)%Construction == 0) THEN
        ErrorsFound = .true.
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                               '", invalid '//TRIM(cAlphaFieldNames(ArgPointer))//'="'//TRIM(cAlphaArgs(ArgPointer))//'".')
      ELSEIF (Construct(SurfaceTmp(SurfNum)%Construction)%TypeIsWindow) THEN
        ErrorsFound = .true.
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                               '", invalid '//TRIM(cAlphaFieldNames(ArgPointer))//'="'//TRIM(cAlphaArgs(ArgPointer))//  &
                               '" - has Window materials.')
        IF (Item == 1) THEN
          CALL ShowContinueError('...because '//TRIM(cAlphaFieldNames(2))//'='//TRIM(cAlphaArgs(2)))
        ELSE
          CALL ShowContinueError('...because Surface Type='//trim(BaseSurfCls(ClassItem)))
        ENDIF
      ELSE
        Construct(SurfaceTmp(SurfNum)%Construction)%IsUsed=.true.
        SurfaceTmp(SurfNum)%ConstructionStoredInputValue  = SurfaceTmp(SurfNum)%Construction
      END IF
      SurfaceTmp(SurfNum)%HeatTransSurf=.true.
      SurfaceTmp(SurfNum)%BaseSurf = SurfNum
      SurfaceTmp(SurfNum)%BaseSurfName=SurfaceTmp(SurfNum)%Name

      ArgPointer=ArgPointer+1
      SurfaceTmp(SurfNum)%ZoneName=cAlphaArgs(ArgPointer)
      ZoneNum=FindItemInList(SurfaceTmp(SurfNum)%ZoneName,Zone%Name,NumOfZones)

      IF (ZoneNum /= 0) THEN
        SurfaceTmp(SurfNum)%Zone = ZoneNum
      ELSE
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                               '", invalid '//TRIM(cAlphaFieldNames(ArgPointer))//'="'//TRIM(cAlphaArgs(ArgPointer))//'".')
        SurfaceTmp(SurfNum)%Class=SurfaceTmp(SurfNum)%Class+100
        SurfaceTmp(SurfNum)%ZoneName='Unknown Zone'
        ErrorsFound=.true.
      ENDIF
  ! Get the ExteriorBoundaryCondition flag from input There are 4 conditions that
  ! can take place. The conditions are set with a 0, -1, or -2, or all of the
  ! zone names have to be looked at and generate the interzone array number
      ArgPointer=ArgPointer+1
      SurfaceTmp(SurfNum)%ExtBoundCondName=cAlphaArgs(ArgPointer+1)

      If(SameString(cAlphaArgs(ArgPointer),'Outdoors')) Then
        SurfaceTmp(SurfNum)%ExtBoundCond = ExternalEnvironment

      Else If(SameString(cAlphaArgs(ArgPointer),'Adiabatic'))         Then
        SurfaceTmp(SurfNum)%ExtBoundCond = UnreconciledZoneSurface
        SurfaceTmp(SurfNum)%ExtBoundCondName=SurfaceTmp(SurfNum)%Name

      Else If(SameString(cAlphaArgs(ArgPointer),'Ground'))         Then
        SurfaceTmp(SurfNum)%ExtBoundCond = Ground

        IF (NoGroundTempObjWarning) THEN
          IF (.not. GroundTempObjInput) THEN
            CALL ShowWarningError('GetHTSurfaceData: Surfaces with interface to Ground '//  &
               'found but no "Ground Temperatures" were input.')
            CALL ShowContinueError('Found first in surface='//TRIM(cAlphaArgs(1)))
            CALL ShowContinueError('Defaults, constant throughout the year of ('//TRIM(RoundSigDigits(GroundTemp,1))// &
                               ') will be used.')
          ENDIF
          NoGroundTempObjWarning=.false.
        ENDIF

      ! Added for FCfactor method
      Else If(SameString(cAlphaArgs(ArgPointer),'GroundFCfactorMethod'))         Then
        SurfaceTmp(SurfNum)%ExtBoundCond = GroundFCfactorMethod
        IF (NoFCGroundTempObjWarning) THEN
          IF (.not. FCGroundTemps) THEN
            CALL ShowSevereError('GetHTSurfaceData: Surfaces with interface to GroundFCfactorMethod found '//  &
                'but no "FC Ground Temperatures" were input.')
            CALL ShowContinueError('Found first in surface='//TRIM(cAlphaArgs(1)))
            CALL ShowContinueError('Either add a "Site:GroundTemperature:FCfactorMethod" object or '//  &
                ' use a weather file with Ground Temperatures.')
            ErrorsFound=.true.
            NoFCGroundTempObjWarning=.false.
          ENDIF
        End IF
        IF (SurfaceTmp(SurfNum)%Construction > 0) THEN
          IF (SurfaceTmp(SurfNum)%Class == SurfaceClass_Wall .and.   &
              .not. Construct(SurfaceTmp(SurfNum)%Construction)%TypeIsCfactorWall) THEN
            CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                                 '", invalid '//TRIM(cAlphaFieldNames(ArgPointer)))
            CALL ShowContinueError('Construction="'//trim(Construct(SurfaceTmp(SurfNum)%Construction)%Name)//  &
               '" is not type Construction:CfactorUndergroundWall.')
          ErrorsFound=.true.
          ENDIF
          IF (SurfaceTmp(SurfNum)%Class == SurfaceClass_Floor .and.   &
              .not. Construct(SurfaceTmp(SurfNum)%Construction)%TypeIsFfactorFloor) THEN
            CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                                 '", invalid '//TRIM(cAlphaFieldNames(ArgPointer)))
            CALL ShowContinueError('Construction="'//trim(Construct(SurfaceTmp(SurfNum)%Construction)%Name)//  &
               '" is not type Construction:FfactorGroundFloor.')
          ErrorsFound=.true.
          ENDIF
        ENDIF

      Else If(SameString(cAlphaArgs(ArgPointer),'OtherSideCoefficients')) Then
        Found=FindItemInList(SurfaceTmp(SurfNum)%ExtBoundCondName,OSC%Name,TotOSC)
        IF (Found == 0) THEN
          CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                      '", invalid '//TRIM(cAlphaFieldNames(ArgPointer+1))//'="'//TRIM(cAlphaArgs(ArgPointer+1))//'".')
          CALL ShowContinueError(' no OtherSideCoefficients of that name.')
          ErrorsFound=.true.
        ELSE
          SurfaceTmp(SurfNum)%OSCPtr=Found
          IF (OSC(Found)%SurfFilmCoef > 0.0d0) THEN
            SurfaceTmp(SurfNum)%ExtBoundCond = OtherSideCoefCalcExt
          ELSE
            SurfaceTmp(SurfNum)%ExtBoundCond = OtherSideCoefNoCalcExt
          ENDIF
        ENDIF

      Else If (SameString(cAlphaArgs(ArgPointer),'Surface')) Then
            ! it has to be another surface which needs to be found
            ! this will be found on the second pass through the surface input
            ! for flagging, set the value to UnreconciledZoneSurface
        ! name (ExtBoundCondName) will be validated later.
        SurfaceTmp(SurfNum)%ExtBoundCond = UnreconciledZoneSurface
        IF (lAlphaFieldBlanks(ArgPointer+1)) THEN
          SurfaceTmp(SurfNum)%ExtBoundCondName=SurfaceTmp(SurfNum)%Name
          CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                        '", invalid '//TRIM(cAlphaFieldNames(ArgPointer+1))//'=<blank>.')
          CALL ShowContinueError('..'//trim(cAlphaFieldNames(ArgPointer))//'="Surface" must be non-blank.')
          CALL ShowContinueError('..This surface will become an adiabatic surface - no doors/windows allowed.')
        ENDIF

      Else If (SameString(cAlphaArgs(ArgPointer),'Zone')) Then
            ! This is the code for an unmatched "other surface"
            ! will be set up later.
        SurfaceTmp(SurfNum)%ExtBoundCond = UnenteredAdjacentZoneSurface
        ! check OutsideFaceEnvironment for legal zone
        Found=FindItemInList(SurfaceTmp(SurfNum)%ExtBoundCondName,Zone%Name,NumOfZones)
        NeedToAddSurfaces=NeedToAddSurfaces+1

        IF (Found == 0) THEN
          CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                        '", invalid '//TRIM(cAlphaFieldNames(ArgPointer))//'="'//TRIM(cAlphaArgs(ArgPointer))//'".')
          CALL ShowContinueError('..Referenced as Zone for this surface.')
          ErrorsFound=.true.
        ENDIF

      ELSE IF (SameString(cAlphaArgs(ArgPointer), 'OtherSideConditionsModel')) Then
        Found=FindItemInList(SurfaceTmp(SurfNum)%ExtBoundCondName,OSCM%Name,TotOSCM)
        IF (Found == 0) THEN
          CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                        '", invalid '//TRIM(cAlphaFieldNames(ArgPointer))//'="'//TRIM(cAlphaArgs(ArgPointer))//'".')
          ErrorsFound=.true.
        ENDIF
        SurfaceTmp(SurfNum)%OSCMPtr=Found
        SurfaceTmp(SurfNum)%ExtBoundCond = OtherSideCondModeledExt

      Else If (SameString(cAlphaArgs(ArgPointer),'GroundSlabPreprocessorAverage')          .or.  &
               SameString(cAlphaArgs(ArgPointer),'GroundSlabPreprocessorCore')             .or.  &
               SameString(cAlphaArgs(ArgPointer),'GroundSlabPreprocessorPerimeter')        .or.  &
               SameString(cAlphaArgs(ArgPointer),'GroundBasementPreprocessorAverageFloor') .or.  &
               SameString(cAlphaArgs(ArgPointer),'GroundBasementPreprocessorAverageWall')  .or.  &
               SameString(cAlphaArgs(ArgPointer),'GroundBasementPreprocessorUpperWall')    .or.  &
               SameString(cAlphaArgs(ArgPointer),'GroundBasementPreprocessorLowerWall') )  Then
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                      '", invalid '//TRIM(cAlphaFieldNames(ArgPointer))//'="'//TRIM(cAlphaArgs(ArgPointer))//'".')
        CALL ShowContinueError('The ExpandObjects program has not been run or is not in your EnergyPlus.exe folder.')
        ErrorsFound=.true.

      Else
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                      '", invalid '//TRIM(cAlphaFieldNames(ArgPointer))//'="'//TRIM(cAlphaArgs(ArgPointer))//'".')
        CALL ShowContinueError('Should be one of "Outdoors", "Adiabatic", Ground", "Surface",'//  &
                               ' "OtherSideCoefficients", "OtherSideConditionsModel" or "Zone"')
        ErrorsFound=.true.
      End If  ! ... End of the ExtBoundCond logical IF Block


      ArgPointer=ArgPointer+2
      !Set the logical flag for the exterior solar
      IF (SameString(cAlphaArgs(ArgPointer),'SunExposed')) THEN
        SurfaceTmp(SurfNum)%ExtSolar=.true.

        IF ((SurfaceTmp(SurfNum)%ExtBoundCond /= ExternalEnvironment) .AND. &
            (SurfaceTmp(SurfNum)%ExtBoundCond /= OtherSideCondModeledExt) ) THEN
          CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                         '", '//TRIM(cAlphaFieldNames(ArgPointer))//'="'//TRIM(cAlphaArgs(ArgPointer))//'".')
          CALL ShowContinueError('..This surface is not exposed to External Environment.  Sun exposure has no effect.')
        ENDIF

      ELSE IF (SameString(cAlphaArgs(ArgPointer),'NoSun')) THEN
        SurfaceTmp(SurfNum)%ExtSolar=.false.
      ELSE
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                      '", invalid '//TRIM(cAlphaFieldNames(ArgPointer))//'="'//TRIM(cAlphaArgs(ArgPointer))//'".')
        ErrorsFound=.true.
      END IF

      ArgPointer=ArgPointer+1
      !Set the logical flag for the exterior wind
      If (SameString(cAlphaArgs(ArgPointer),'WindExposed')) THEN
        SurfaceTmp(SurfNum)%ExtWind=.true.
      ElseIf (SameString(cAlphaArgs(ArgPointer),'NoWind')) THEN
        SurfaceTmp(SurfNum)%ExtWind=.false.
      Else
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                      '", invalid '//TRIM(cAlphaFieldNames(ArgPointer))//'="'//TRIM(cAlphaArgs(ArgPointer))//'".')
        ErrorsFound=.true.
      End If

      !Set the logical flag for the EcoRoof presented, this is only based on the flag in the construction type
      IF (SurfaceTmp(SurfNum)%Construction > 0) &
        SurfaceTmp(SurfNum)%ExtEcoRoof=Construct(SurfaceTmp(SurfNum)%Construction)%TypeIsEcoRoof

      SurfaceTmp(SurfNum)%ViewFactorGround = rNumericArgs(1)
      IF (lNumericFieldBlanks(1)) SurfaceTmp(SurfNum)%ViewFactorGround = AutoCalculate
      IF (lNumericFieldBlanks(2) .or. rNumericArgs(2) == AutoCalculate) THEN
        numSides=(SurfaceNumProp-2)/3
        SurfaceTmp(SurfNum)%Sides=numSides
        IF (MOD(SurfaceNumProp-2,3) /= 0) THEN
          CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                          '", '//TRIM(cNumericFieldNames(2))//          &
                          ' not even multiple of 3. Will read in '//   &
                          TRIM(TrimSigDigits(SurfaceTmp(SurfNum)%Sides)))
        ENDIF
        IF (numSides < 3) THEN
          CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                         '", '//TRIM(cNumericFieldNames(2))//' (autocalculate) must be >= 3. Only '//  &
                         TRIM(TrimSigDigits(SurfaceTmp(SurfNum)%Sides))//' provided.')
          ErrorsFound=.true.
          CYCLE
        ENDIF
      ELSE
        numSides=(SurfaceNumProp-2)/3
        SurfaceTmp(SurfNum)%Sides=rNumericArgs(2)
        IF (numSides > SurfaceTmp(SurfNum)%Sides) THEN
          CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                          '", field '//TRIM(cNumericFieldNames(2))//'='//TRIM(TrimSigDigits(SurfaceTmp(SurfNum)%Sides)))
          CALL ShowContinueError('...but '//TRIM(TrimSigDigits(numSides))//' were entered. Only the indicated '//  &
                          TRIM(cNumericFieldNames(2))//' will be used.')
        ENDIF
      ENDIF
      ALLOCATE(SurfaceTmp(SurfNum)%Vertex(SurfaceTmp(SurfNum)%Sides))
      CALL GetVertices(SurfNum,SurfaceTmp(SurfNum)%Sides,rNumericArgs(3:))
      IF (SurfaceTmp(SurfNum)%Area <= 0.0d0) THEN
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
              '", Surface Area <= 0.0; Entered Area='//  &
              TRIM(TrimSigDigits(SurfaceTmp(SurfNum)%Area,2)))
        ErrorsFound=.true.
      ENDIF

      CALL CheckConvexity(SurfNum,SurfaceTmp(SurfNum)%Sides)
      IF (SurfaceTmp(SurfNum)%Construction > 0) THEN
        !Check wall height for the CFactor walls
        IF (SurfaceTmp(SurfNum)%Class == SurfaceClass_Wall .and.   &
            Construct(SurfaceTmp(SurfNum)%Construction)%TypeIsCfactorWall) THEN
          IF (ABS(SurfaceTmp(SurfNum)%Height - Construct(SurfaceTmp(SurfNum)%Construction)%Height)>0.05d0) THEN
            CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                       '", underground Wall Height = '//TRIM(TrimSigDigits(SurfaceTmp(SurfNum)%Height,2)))
            CALL ShowContinueError('..which does not match its construction height.')
          ENDIF
        ENDIF

        !Check area and perimeter for the FFactor floors
        IF (SurfaceTmp(SurfNum)%Class == SurfaceClass_Floor .and.   &
            Construct(SurfaceTmp(SurfNum)%Construction)%TypeIsFfactorFloor) THEN
          IF (ABS(SurfaceTmp(SurfNum)%Area - Construct(SurfaceTmp(SurfNum)%Construction)%Area)>0.1d0) THEN
            CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                       '", underground Floor Area = '//TRIM(TrimSigDigits(SurfaceTmp(SurfNum)%Area,2)))
            CALL ShowContinueError('..which does not match its construction area.')
          ENDIF
          IF (SurfaceTmp(SurfNum)%Perimeter < Construct(SurfaceTmp(SurfNum)%Construction)%PerimeterExposed - 0.1d0) THEN
            CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                       '", underground Floor Perimeter = '//TRIM(TrimSigDigits(SurfaceTmp(SurfNum)%Perimeter,2)))
            CALL ShowContinueError('..which is less than its construction exposed perimeter.')
          ENDIF
        ENDIF
      ENDIF

    ENDDO
  ENDDO  ! Item Looop
  RETURN

END SUBROUTINE GetHTSurfaceData

SUBROUTINE GetRectSurfaces(ErrorsFound,SurfNum,TotRectExtWalls,TotRectIntWalls,TotRectIZWalls,TotRectUGWalls,  &
      TotRectRoofs,TotRectCeilings,TotRectIZCeilings,TotRectGCFloors,TotRectIntFloors,TotRectIZFloors,     &
      BaseSurfIDs,NeedToAddSurfaces)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Linda Lawrie
          !       DATE WRITTEN   December 2008
          !       MODIFIED       na
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! Get simple (rectangular, LLC corner specified) walls

          ! METHODOLOGY EMPLOYED:
          ! na

          ! REFERENCES:
          ! na

          ! USE STATEMENTS:
  USE DataIPShortCuts
  USE InputProcessor, ONLY: GetNumObjectsFound, GetObjectItem, FindItemInList, VerifyName, GetObjectDefMaxArgs
  USE General, ONLY: TrimSigDigits,RoundSigDigits

  IMPLICIT NONE ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
  LOGICAL, INTENT(INOUT)         :: ErrorsFound       ! Error flag indicator (true if errors found)
  INTEGER, INTENT(INOUT)         :: SurfNum           ! Count of Current SurfaceNumber
  INTEGER, INTENT(IN)            :: TotRectExtWalls   ! Number of Exterior Walls to obtain
  INTEGER, INTENT(IN)            :: TotRectIntWalls   ! Number of Adiabatic Walls to obtain
  INTEGER, INTENT(IN)            :: TotRectIZWalls    ! Number of Interzone Walls to obtain
  INTEGER, INTENT(IN)            :: TotRectUGWalls    ! Number of Underground to obtain
  INTEGER, INTENT(IN)            :: TotRectRoofs      ! Number of Roofs to obtain
  INTEGER, INTENT(IN)            :: TotRectCeilings   ! Number of Adiabatic Ceilings to obtain
  INTEGER, INTENT(IN)            :: TotRectIZCeilings ! Number of Interzone Ceilings to obtain
  INTEGER, INTENT(IN)            :: TotRectGCFloors   ! Number of Floors with Ground Contact to obtain
  INTEGER, INTENT(IN)            :: TotRectIntFloors  ! Number of Adiabatic Walls to obtain
  INTEGER, INTENT(IN)            :: TotRectIZFloors   ! Number of Interzone Floors to obtain
  INTEGER, DIMENSION(:), INTENT(IN) :: BaseSurfIDs    ! ID Assignments for valid surface classes
  INTEGER, INTENT(INOUT)         :: NeedToAddSurfaces ! Number of surfaces to add, based on unentered IZ surfaces

          ! SUBROUTINE PARAMETER DEFINITIONS:
  CHARACTER(len=*), PARAMETER, DIMENSION(10) :: cModuleObjects=  &
    (/'Wall:Exterior      ',  &
      'Wall:Adiabatic     ',  &
      'Wall:Interzone     ',  &
      'Wall:Underground   ',  &
      'Roof               ',  &
      'Ceiling:Adiabatic  ',  &
      'Ceiling:Interzone  ',  &
      'Floor:GroundContact',  &
      'Floor:Adiabatic    ',  &
      'Floor:Interzone    '/)


          ! INTERFACE BLOCK SPECIFICATIONS:
          ! na

          ! DERIVED TYPE DEFINITIONS:
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
          ! na

  INTEGER :: Item
  INTEGER :: ItemsToGet
  INTEGER :: Loop
  INTEGER :: NumAlphas
  INTEGER :: NumNumbers
  INTEGER :: IOStat            ! IO Status when calling get input subroutine
  INTEGER :: Found             ! For matching base surfaces
  LOGICAL :: ErrorInName
  LOGICAL :: IsBlank
  LOGICAL :: GettingIZSurfaces
  INTEGER :: OtherSurfaceField
  INTEGER :: ExtBoundCondition
  INTEGER :: ClassItem
  INTEGER :: ZoneNum

  DO Item=1,10

    cCurrentModuleObject=cModuleObjects(Item)
    IF (Item == 1) THEN
      ItemsToGet=TotRectExtWalls
      GettingIZSurfaces=.false.
      OtherSurfaceField=0
      ExtBoundCondition=ExternalEnvironment
      ClassItem=1
    ELSEIF (Item == 2) THEN
      ItemsToGet=TotRectIntWalls
      GettingIZSurfaces=.false.
      OtherSurfaceField=0
      ExtBoundCondition=UnreconciledZoneSurface
      ClassItem=1
    ELSEIF (Item == 3) THEN
      ItemsToGet=TotRectIZWalls
      GettingIZSurfaces=.true.
      OtherSurfaceField=4
      ExtBoundCondition=UnreconciledZoneSurface
      ClassItem=1
    ELSEIF (Item == 4) THEN
      ItemsToGet=TotRectUGWalls
      GettingIZSurfaces=.false.
      OtherSurfaceField=0
      ExtBoundCondition=Ground
      ClassItem=1
    ELSEIF (Item == 5) THEN
      ItemsToGet=TotRectRoofs
      GettingIZSurfaces=.false.
      OtherSurfaceField=0
      ExtBoundCondition=ExternalEnvironment
      ClassItem=3
    ELSEIF (Item == 6) THEN
      ItemsToGet=TotRectCeilings
      GettingIZSurfaces=.false.
      OtherSurfaceField=0
      ExtBoundCondition=UnreconciledZoneSurface
      ClassItem=3
    ELSEIF (Item == 7) THEN
      ItemsToGet=TotRectIZCeilings
      GettingIZSurfaces=.false.
      OtherSurfaceField=4
      ExtBoundCondition=UnreconciledZoneSurface
      ClassItem=3
    ELSEIF (Item == 8) THEN
      ItemsToGet=TotRectGCFloors
      GettingIZSurfaces=.false.
      OtherSurfaceField=0
      ExtBoundCondition=Ground
      ClassItem=2
    ELSEIF (Item == 9) THEN
      ItemsToGet=TotRectIntFloors
      GettingIZSurfaces=.false.
      OtherSurfaceField=0
      ExtBoundCondition=UnreconciledZoneSurface
      ClassItem=2
    ELSE  !IF (Item == 10) THEN
      ItemsToGet=TotRectIZFloors
      GettingIZSurfaces=.true.
      OtherSurfaceField=4
      ExtBoundCondition=UnreconciledZoneSurface
      ClassItem=2
    ENDIF

    DO Loop=1,ItemsToGet
      CALL GetObjectItem(cCurrentModuleObject,Loop,cAlphaArgs,NumAlphas,rNumericArgs,NumNumbers,IOSTAT,  &
                     AlphaBlank=lAlphaFieldBlanks,NumBlank=lNumericFieldBlanks,  &
                     AlphaFieldnames=cAlphaFieldNames,NumericFieldNames=cNumericFieldNames)
      ErrorInName=.false.
      IsBlank=.false.
      CALL VerifyName(cAlphaArgs(1),SurfaceTmp%Name,SurfNum,ErrorInName,IsBlank,TRIM(cCurrentModuleObject)//' Name')
      IF (ErrorInName) THEN
        CALL ShowContinueError('...each surface name must not duplicate other surface names (of any type)')
        ErrorsFound=.true.
        CYCLE
      ENDIF

      IF (NumNumbers < 7) THEN
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(cAlphaArgs(1))//  &
                        '", Too few number of numeric args=['//TRIM(TrimSigDigits(NumNumbers))//'].')
        ErrorsFound=.true.
      ENDIF

      SurfNum=SurfNum+1
      SurfaceTmp(SurfNum)%Name = cAlphaArgs(1)  ! Set the Surface Name in the Derived Type
      SurfaceTmp(SurfNum)%Class = BaseSurfIDs(ClassItem) ! Set class number

      SurfaceTmp(SurfNum)%Construction=FindIteminList(cAlphaArgs(2),Construct%Name,TotConstructs)

      IF(SurfaceTmp(SurfNum)%Construction == 0) THEN
        ErrorsFound = .true.
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                               '", invalid '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))//'".')
      ELSEIF (Construct(SurfaceTmp(SurfNum)%Construction)%TypeIsWindow) THEN
        ErrorsFound = .true.
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                               '", invalid '//TRIM(cAlphaFieldNames(3))//'="'//TRIM(cAlphaArgs(2))//  &
                               '" - has Window materials.')
        CALL ShowContinueError('...because '//TRIM(cAlphaFieldNames(2))//'='//TRIM(cAlphaArgs(2)))
      ELSE
        Construct(SurfaceTmp(SurfNum)%Construction)%IsUsed=.true.
        SurfaceTmp(SurfNum)%ConstructionStoredInputValue  = SurfaceTmp(SurfNum)%Construction
      END IF
      SurfaceTmp(SurfNum)%HeatTransSurf=.true.
      SurfaceTmp(SurfNum)%BaseSurf = SurfNum
      SurfaceTmp(SurfNum)%BaseSurfName=SurfaceTmp(SurfNum)%Name

      SurfaceTmp(SurfNum)%ZoneName=cAlphaArgs(3)
      ZoneNum=FindItemInList(SurfaceTmp(SurfNum)%ZoneName,Zone%Name,NumOfZones)

      IF (ZoneNum /= 0) THEN
        SurfaceTmp(SurfNum)%Zone = ZoneNum
      ELSE
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                               '", invalid '//TRIM(cAlphaFieldNames(3))//'="'//TRIM(cAlphaArgs(3))//'".')
        SurfaceTmp(SurfNum)%Class=SurfaceTmp(SurfNum)%Class+100
        SurfaceTmp(SurfNum)%ZoneName='Unknown Zone'
        ErrorsFound=.true.
      ENDIF

      SurfaceTmp(SurfNum)%ExtBoundCond = ExtBoundCondition
      IF (SurfaceTmp(SurfNum)%Construction > 0) THEN
        IF (SurfaceTmp(SurfNum)%Class == SurfaceClass_Wall .and.   &
            Construct(SurfaceTmp(SurfNum)%Construction)%TypeIsCfactorWall .and. &
            SurfaceTmp(SurfNum)%ExtBoundCond == Ground) THEN
              SurfaceTmp(SurfNum)%ExtBoundCond = GroundFCfactorMethod
        ELSEIF (Construct(SurfaceTmp(SurfNum)%Construction)%TypeIsCfactorWall) THEN
          ErrorsFound = .true.
          CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
            '", Construction type is "Construction:CfactorUndergroundWall" but invalid for this object.')
        ENDIF
        IF (SurfaceTmp(SurfNum)%Class == SurfaceClass_Floor .and.   &
            Construct(SurfaceTmp(SurfNum)%Construction)%TypeIsFfactorFloor .and. &
            SurfaceTmp(SurfNum)%ExtBoundCond == Ground) THEN
              SurfaceTmp(SurfNum)%ExtBoundCond = GroundFCfactorMethod
        ELSEIF (Construct(SurfaceTmp(SurfNum)%Construction)%TypeIsFfactorFloor) THEN
          ErrorsFound = .true.
          CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
            '", Construction type is "Construction:FfactorGroundFloor" but invalid for this object.')
        ENDIF
      ENDIF
      SurfaceTmp(SurfNum)%ExtSolar=.false.
      SurfaceTmp(SurfNum)%ExtWind=.false.
      SurfaceTmp(SurfNum)%ViewFactorGround = AutoCalculate

      IF (SurfaceTmp(SurfNum)%ExtBoundCond == ExternalEnvironment) THEN
        SurfaceTmp(SurfNum)%ExtSolar=.true.
        SurfaceTmp(SurfNum)%ExtWind=.true.

        !Set the logical flag for the EcoRoof presented, this is only based on the flag in the construction type
        IF (SurfaceTmp(SurfNum)%Construction > 0) &
          SurfaceTmp(SurfNum)%ExtEcoRoof=Construct(SurfaceTmp(SurfNum)%Construction)%TypeIsEcoRoof

      Else If (SurfaceTmp(SurfNum)%ExtBoundCond == UnreconciledZoneSurface) THEN
        IF (GettingIZSurfaces) THEN
          SurfaceTmp(SurfNum)%ExtBoundCondName=cAlphaArgs(OtherSurfaceField)
          Found=FindItemInList(SurfaceTmp(SurfNum)%ExtBoundCondName,Zone%Name,NumOfZones)
          ! see if match to zone, then it's an unentered other surface, else reconciled later
          IF (Found > 0) THEN
            NeedToAddSurfaces=NeedToAddSurfaces+1
            SurfaceTmp(SurfNum)%ExtBoundCond = UnenteredAdjacentZoneSurface
          ENDIF
        ELSE
          SurfaceTmp(SurfNum)%ExtBoundCondName=SurfaceTmp(SurfNum)%Name
        ENDIF

      Else If (SurfaceTmp(SurfNum)%ExtBoundCond == Ground) THEN

        IF (NoGroundTempObjWarning) THEN
          IF (.not. GroundTempObjInput) THEN
            CALL ShowWarningError('GetRectSurfaces: Surfaces with interface to Ground found '//  &
                 'but no "Ground Temperatures" were input.')
            CALL ShowContinueError('Found first in surface='//TRIM(cAlphaArgs(1)))
            CALL ShowContinueError('Defaults, constant throughout the year of ('//TRIM(RoundSigDigits(GroundTemp,1))// &
                               ') will be used.')
          ENDIF
          NoGroundTempObjWarning=.false.
        ENDIF

      Else If (SurfaceTmp(SurfNum)%ExtBoundCond == GroundFCfactorMethod) THEN
        IF (NoFCGroundTempObjWarning) THEN
          IF (.not. FCGroundTemps) THEN
            CALL ShowSevereError('GetRectSurfaces: Surfaces with interface to GroundFCfactorMethod found '//  &
                'but no "FC Ground Temperatures" were input.')
            CALL ShowContinueError('Found first in surface='//TRIM(cAlphaArgs(1)))
            CALL ShowContinueError('Either add a "Site:GroundTemperature:FCfactorMethod" object or '//  &
                ' use a weather file with Ground Temperatures.')
            ErrorsFound=.true.
            NoFCGroundTempObjWarning=.false.
          ENDIF
        End IF

      End If  ! ... End of the ExtBoundCond logical IF Block

      SurfaceTmp(SurfNum)%Azimuth=rNumericArgs(1)
      SurfaceTmp(SurfNum)%Tilt=rNumericArgs(2)
      IF (.not. WorldCoordSystem) THEN
        IF (ZoneNum /= 0) THEN
          SurfaceTmp(SurfNum)%Azimuth=SurfaceTmp(SurfNum)%Azimuth+BuildingAzimuth+Zone(ZoneNum)%RelNorth
        ENDIF
      ENDIF
      IF (ZoneNum /= 0) THEN
        SurfaceTmp(SurfNum)%Azimuth=SurfaceTmp(SurfNum)%Azimuth+BuildingRotationAppendixG
      ENDIF

      SurfaceTmp(SurfNum)%Sides=4
      ALLOCATE(SurfaceTmp(SurfNum)%Vertex(SurfaceTmp(SurfNum)%Sides))

      CALL MakeRectangularVertices(SurfNum,rNumericArgs(3),  &
                                   rNumericArgs(4),rNumericArgs(5),rNumericArgs(6),rNumericArgs(7),RectSurfRefWorldCoordSystem)

      IF (SurfaceTmp(SurfNum)%Area <= 0.0d0) THEN
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
              '", Surface Area <= 0.0; Entered Area='//  &
              TRIM(TrimSigDigits(SurfaceTmp(SurfNum)%Area,2)))
        ErrorsFound=.true.
      ENDIF

      !Check wall height for the CFactor walls
      IF (SurfaceTmp(SurfNum)%Class == SurfaceClass_Wall .and. SurfaceTmp(SurfNum)%ExtBoundCond == GroundFCfactorMethod) THEN
        IF (ABS(SurfaceTmp(SurfNum)%Height - Construct(SurfaceTmp(SurfNum)%Construction)%Height)>0.05d0) THEN
          CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                     '", underground Wall Height = '//TRIM(TrimSigDigits(SurfaceTmp(SurfNum)%Height,2)))
          CALL ShowContinueError('..which deos not match its construction height.')
        ENDIF
      ENDIF

      !Check area and perimeter for the FFactor floors
      IF (SurfaceTmp(SurfNum)%Class == SurfaceClass_Floor .and. SurfaceTmp(SurfNum)%ExtBoundCond == GroundFCfactorMethod) THEN
        IF (ABS(SurfaceTmp(SurfNum)%Area - Construct(SurfaceTmp(SurfNum)%Construction)%Area)>0.1d0) THEN
          CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                     '", underground Floor Area = '//TRIM(TrimSigDigits(SurfaceTmp(SurfNum)%Area,2)))
          CALL ShowContinueError('..which does not match its construction area.')
        ENDIF
        IF (SurfaceTmp(SurfNum)%Perimeter < Construct(SurfaceTmp(SurfNum)%Construction)%PerimeterExposed - 0.1d0) THEN
          CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                     '", underground Floor Perimeter = '//TRIM(TrimSigDigits(SurfaceTmp(SurfNum)%Perimeter,2)))
          CALL ShowContinueError('..which is less than its construction exposed perimeter.')
        ENDIF
      ENDIF
    ENDDO  ! Getting Items

  ENDDO

  RETURN

END SUBROUTINE GetRectSurfaces

SUBROUTINE MakeRectangularVertices(SurfNum,XCoord,YCoord,ZCoord,Length,Height,SurfWorldCoordSystem)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Linda Lawrie
          !       DATE WRITTEN   December 2008
          !       MODIFIED       na
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! This routine creates world/3d coordinates for rectangular surfaces using azimuth, tilt, LLC (X,Y,Z), length & height.

          ! METHODOLOGY EMPLOYED:
          ! na

          ! REFERENCES:
          ! na

          ! USE STATEMENTS:
  USE Vectors

  IMPLICIT NONE ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
  INTEGER, INTENT(IN) :: SurfNum
  REAL(r64), INTENT(IN) :: XCoord
  REAL(r64), INTENT(IN) :: YCoord
  REAL(r64), INTENT(IN) :: ZCoord
  REAL(r64), INTENT(IN) :: Length
  REAL(r64), INTENT(IN) :: Height
  LOGICAL, INTENT(IN) :: SurfWorldCoordSystem

          ! SUBROUTINE PARAMETER DEFINITIONS:
          ! na

          ! INTERFACE BLOCK SPECIFICATIONS:
          ! na

          ! DERIVED TYPE DEFINITIONS:
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
  REAL(r64) :: SurfAzimuth  ! Surface Azimuth/Facing (same as Base Surface)
  REAL(r64) :: SurfTilt     ! Tilt (same as Base Surface)
  REAL(r64) :: XLLC
  REAL(r64) :: YLLC
  REAL(r64) :: ZLLC
  REAL(r64) :: CosSurfAzimuth
  REAL(r64) :: SinSurfAzimuth
  REAL(r64) :: CosSurfTilt
  REAL(r64) :: SinSurfTilt
  REAL(r64) :: XX(4),YY(4)
  REAL(r64) :: Xb, Yb
  REAL(r64) :: Perimeter
  INTEGER :: N
  INTEGER :: Vrt

  IF (SurfaceTmp(SurfNum)%Zone == 0 .and. &
     (SurfaceTmp(SurfNum)%Class /= SurfaceClass_Detached_F .and.   &
      SurfaceTmp(SurfNum)%Class /= SurfaceClass_Detached_B)) RETURN

  SurfaceTmp(SurfNum)%Height=Height
  SurfaceTmp(SurfNum)%Width=Length

  SurfAzimuth = SurfaceTmp(SurfNum)%Azimuth
  SurfTilt    = SurfaceTmp(SurfNum)%Tilt
  CosSurfAzimuth=COS(SurfAzimuth*DegToRadians)
  SinSurfAzimuth=SIN(SurfAzimuth*DegToRadians)
  CosSurfTilt=COS(SurfTilt*DegToRadians)
  SinSurfTilt=SIN(SurfTilt*DegToRadians)
  IF (.not. SurfWorldCoordSystem) THEN
    IF (SurfaceTmp(SurfNum)%Zone > 0) THEN
      Xb    = XCoord*CosZoneRelNorth(SurfaceTmp(SurfNum)%Zone) &
             -YCoord*SinZoneRelNorth(SurfaceTmp(SurfNum)%Zone) + Zone(SurfaceTmp(SurfNum)%Zone)%OriginX
      Yb    = XCoord*SinZoneRelNorth(SurfaceTmp(SurfNum)%Zone) &
             +YCoord*CosZoneRelNorth(SurfaceTmp(SurfNum)%Zone) + Zone(SurfaceTmp(SurfNum)%Zone)%OriginY
      XLLC  = Xb*CosBldgRelNorth - Yb*SinBldgRelNorth
      YLLC  = Xb*SinBldgRelNorth + Yb*CosBldgRelNorth
      ZLLC  = ZCoord + Zone(SurfaceTmp(SurfNum)%Zone)%OriginZ
    ELSE
      IF (SurfaceTmp(SurfNum)%Class == SurfaceClass_Detached_B) THEN
        Xb    = XCoord
        Yb    = YCoord
        XLLC  = Xb*CosBldgRelNorth - Yb*SinBldgRelNorth
        YLLC  = Xb*SinBldgRelNorth + Yb*CosBldgRelNorth
        ZLLC  = ZCoord
      ELSE
        XLLC  = XCoord
        YLLC  = YCoord
        ZLLC  = ZCoord
      ENDIF
    ENDIF
  ELSE
    ! for world coordinates, only rotate for appendix G
    Xb  = XCoord
    Yb  = YCoord
    ZLLC  = ZCoord
    IF (SurfaceTmp(SurfNum)%Class /= SurfaceClass_Detached_F) THEN
      XLLC= Xb*CosBldgRotAppGonly - Yb*SinBldgRotAppGonly
      YLLC= Xb*SinBldgRotAppGonly + Yb*CosBldgRotAppGonly
    ELSE
      XLLC = Xb
      YLLC = Yb
    ENDIF
  ENDIF

  XX(1)=0.0d0
  XX(2)=0.0d0
  XX(3)=Length
  XX(4)=Length
  YY(1)=Height
  YY(4)=Height
  YY(3)=0.0d0
  YY(2)=0.0d0

  DO N = 1, SurfaceTmp(SurfNum)%Sides
    Vrt=N
    SurfaceTmp(SurfNum)%Vertex(Vrt)%X=XLLC-XX(N)*CosSurfAzimuth-YY(N)*CosSurfTilt*SinSurfAzimuth
    SurfaceTmp(SurfNum)%Vertex(Vrt)%Y=YLLC+XX(N)*SinSurfAzimuth-YY(N)*CosSurfTilt*CosSurfAzimuth
    SurfaceTmp(SurfNum)%Vertex(Vrt)%Z=ZLLC+YY(N)*SinSurfTilt
  END DO

  CALL CreateNewellAreaVector(SurfaceTmp(SurfNum)%Vertex,SurfaceTmp(SurfNum)%Sides,SurfaceTmp(SurfNum)%NewellAreaVector)
  SurfaceTmp(SurfNum)%GrossArea=VecLength(SurfaceTmp(SurfNum)%NewellAreaVector)
  SurfaceTmp(SurfNum)%Area=SurfaceTmp(SurfNum)%GrossArea
  SurfaceTmp(SurfNum)%NetAreaShadowCalc = SurfaceTmp(SurfNum)%Area
  CALL CreateNewellSurfaceNormalVector(SurfaceTmp(SurfNum)%Vertex,SurfaceTmp(SurfNum)%Sides,  &
     SurfaceTmp(SurfNum)%NewellSurfaceNormalVector)
  CALL DetermineAzimuthAndTilt(SurfaceTmp(SurfNum)%Vertex,SurfaceTmp(SurfNum)%Sides,SurfAzimuth,SurfTilt,  &
                               SurfaceTmp(SurfNum)%lcsx,SurfaceTmp(SurfNum)%lcsy,SurfaceTmp(SurfNum)%lcsz, &
                               SurfaceTmp(SurfNum)%GrossArea,SurfaceTmp(SurfNum)%NewellSurfaceNormalVector)
  SurfaceTmp(SurfNum)%Azimuth=SurfAzimuth
  SurfaceTmp(SurfNum)%Tilt=SurfTilt
  ! Sine and cosine of azimuth and tilt
  SurfaceTmp(SurfNum)%SinAzim = SinSurfAzimuth
  SurfaceTmp(SurfNum)%CosAzim = CosSurfAzimuth
  SurfaceTmp(SurfNum)%SinTilt = SinSurfTilt
  SurfaceTmp(SurfNum)%CosTilt = CosSurfTilt
  SurfaceTmp(SurfNum)%ViewFactorGround = 0.5d0 * (1.0d0 - SurfaceTmp(SurfNum)%CosTilt)
  ! 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_Roof .and. SurfTilt > 80.) THEN
!    WRITE(TiltString,'(F5.1)') SurfTilt
!    TiltString=ADJUSTL(TiltString)
!    CALL ShowWarningError('Roof/Ceiling Tilt='//TRIM(TiltString)//', much greater than expected tilt of 0,'// &
!                          ' for Surface='//TRIM(SurfaceTmp(SurfNum)%Name)//  &
!                          ', in Zone='//TRIM(SurfaceTmp(SurfNum)%ZoneName))
!  ENDIF
!  IF (SurfaceTmp(SurfNum)%Class == SurfaceClass_Floor .and. SurfTilt < 170.) THEN
!    WRITE(TiltString,'(F5.1)') SurfTilt
!    TiltString=ADJUSTL(TiltString)
!    CALL ShowWarningError('Floor Tilt='//TRIM(TiltString)//', much less than expected tilt of 180,'//   &
!                          ' for Surface='//TRIM(SurfaceTmp(SurfNum)%Name)//  &
!                          ', in Zone='//TRIM(SurfaceTmp(SurfNum)%ZoneName))
!  ENDIF

  ! 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)

  Perimeter=Distance(SurfaceTmp(SurfNum)%Vertex(SurfaceTmp(SurfNum)%Sides),SurfaceTmp(SurfNum)%Vertex(1))
  DO Vrt=2,SurfaceTmp(SurfNum)%Sides
    Perimeter = Perimeter+Distance(SurfaceTmp(SurfNum)%Vertex(Vrt),SurfaceTmp(SurfNum)%Vertex(Vrt-1))
  ENDDO
  SurfaceTmp(SurfNum)%Perimeter=Perimeter

  ! Call to transform vertices

  Call TransformVertsByAspect(SurfNum,SurfaceTmp(SurfNum)%Sides)

  RETURN

END SUBROUTINE MakeRectangularVertices

SUBROUTINE GetHTSubSurfaceData(ErrorsFound,SurfNum,TotHTSubs,SubSurfCls,SubSurfIDs,AddedSubSurfaces,NeedToAddSurfaces)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Linda Lawrie
          !       DATE WRITTEN   May 2000
          !       MODIFIED       August 2012 - line up subsurfaces with base surface types
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! This subroutine gets the HeatTransfer Sub Surface Data,
          ! checks it for errors, etc.

          ! METHODOLOGY EMPLOYED:
          ! na

          ! REFERENCES:
  ! Heat Transfer Subsurface Definition
  ! FenestrationSurface:Detailed,
  !        \min-fields 19
  !        \memo Used for windows, doors, glass doors, tubular daylighting devices
  !        \format vertices
  !   A1 , \field Name
  !        \required-field
  !        \type alpha
  !   A2 , \field Surface Type
  !        \required-field
  !        \type choice
  !        \key Window
  !        \key Door
  !        \key GlassDoor
  !        \key TubularDaylightDome
  !        \key TubularDaylightDiffuser
  !   A3 , \field Construction Name
  !        \required-field
  !        \note To be matched with a construction in this input file
  !        \type object-list
  !        \object-list ConstructionNames
  !   A4 , \field Building Surface Name
  !        \required-field
  !        \type object-list
  !        \object-list SurfaceNames
  !   A5,  \field Outside Boundary Condition Object
  !        \type object-list
  !        \object-list OutFaceEnvNames
  !        \note Non-blank only if base surface field Outside Boundary Condition is
  !        \note Surface or OtherSideCoefficients
  !        \note If Base Surface's Surface, specify name of corresponding subsurface in adjacent zone or
  !        \note specify current subsurface name for internal partition separating like zones
  !        \note If OtherSideCoefficients, specify name of SurfaceProperty:OtherSideCoefficients
  !        \note  or leave blank to inherit Base Surface's OtherSide Coefficients
  !   N1, \field View Factor to Ground
  !        \type real
  !        \note From the exterior of the surface
  !        \note Unused if one uses the "reflections" options in Solar Distribution in Building input
  !        \note unless a DaylightingDevice:Shelf or DaylightingDevice:Tubular object has been specified.
  !        \note autocalculate will automatically calculate this value from the tilt of the surface
  !        \autocalculatable
  !        \minimum 0.0
  !        \maximum 1.0
  !        \default autocalculate
  !   A6, \field Shading Control Name
  !        \note enter the name of a WindowProperty:ShadingControl object
  !        \type object-list
  !        \object-list WindowShadeControlNames
  !        \note used for windows and glass doors only
  !        \note If not specified, window or glass door has no shading (blind, roller shade, etc.)
  !   A7, \field Frame and Divider Name
  !        \note Enter the name of a WindowProperty:FrameAndDivider object
  !        \type object-list
  !        \object-list WindowFrameAndDividerNames
  !        \note Used only for exterior windows (rectangular) and glass doors.
  !        \note Unused for triangular windows.
  !        \note If not specified (blank), window or glass door has no frame or divider
  !        \note and no beam solar reflection from reveal surfaces.
  !   N2 , \field Multiplier
  !        \note Used only for Surface Type = WINDOW, GLASSDOOR or DOOR
  !        \note Non-integer values will be truncated to integer
  !        \default 1.0
  !        \minimum 1.0
  !   N3 , \field Number of Vertices
  !        \minimum 3
  !        \maximum 4
  !        \autocalculatable
  !        \default autocalculate
  !        \note vertices are given in GlobalGeometryRules coordinates -- if relative, all surface coordinates
  !        \note are "relative" to the Zone Origin.  If world, then building and zone origins are used
  !        \note for some internal calculations, but all coordinates are given in an "absolute" system.
  !  N4-15 as indicated by the N3 value

          ! USE STATEMENTS:
  USE DataIPShortCuts
  USE InputProcessor, ONLY: GetNumObjectsFound, GetObjectItem, FindItemInList, VerifyName, GetObjectDefMaxArgs
  USE General, ONLY: TrimSigDigits,RoundSigDigits

  IMPLICIT NONE    ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
  LOGICAL, INTENT(INOUT)         :: ErrorsFound       ! Error flag indicator (true if errors found)
  INTEGER, INTENT(INOUT)         :: SurfNum           ! Count of Current SurfaceNumber
  INTEGER, INTENT(IN)            :: TotHTSubs         ! Number of Heat Transfer SubSurfaces to obtain
  CHARACTER(len=*), DIMENSION(:), INTENT(IN) :: SubSurfCls   ! Valid Classes for Sub Surfaces
  INTEGER, DIMENSION(:), INTENT(IN) :: SubSurfIDs     ! ID Assignments for valid sub surface classes
  INTEGER, INTENT(INOUT)         :: AddedSubSurfaces  ! Subsurfaces added when windows reference Window5
                                                      !  data file entry with two glazing systems
  INTEGER, INTENT(OUT)           :: NeedToAddSurfaces ! Number of surfaces to add, based on unentered IZ surfaces

          ! SUBROUTINE PARAMETER DEFINITIONS:
          ! na

          ! INTERFACE BLOCK SPECIFICATIONS
          ! na

          ! DERIVED TYPE DEFINITIONS
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
  INTEGER :: IOStat            ! IO Status when calling get input subroutine
  INTEGER :: SurfaceNumAlpha   ! Number of material alpha names being passed
  INTEGER :: SurfaceNumProp    ! Number of material properties being passed
  INTEGER :: Found             ! For matching interzone surfaces
  INTEGER :: Loop
  LOGICAL :: ErrorInName
  LOGICAL :: IsBlank
  INTEGER :: ValidChk
  INTEGER :: numSides

  CALL GetWindowShadingControlData(ErrorsFound)

  cCurrentModuleObject='FenestrationSurface:Detailed'
  CALL GetObjectDefMaxArgs(cCurrentModuleObject,Loop,SurfaceNumAlpha,SurfaceNumProp)

  IF (SurfaceNumAlpha /= 7) THEN
    CALL ShowSevereError(TRIM(cCurrentModuleObject)//': Object Definition indicates '// &
                         'not = 7 Alpha Objects, Number Indicated='//  &
                         TRIM(TrimSigDigits(SurfaceNumAlpha)))
    ErrorsFound=.true.
  ENDIF

  IF (SurfaceNumProp /= 15) THEN
    CALL ShowSevereError(TRIM(cCurrentModuleObject)//': Object Definition indicates '// &
                         '> 15 Numeric Objects, Number Indicated='//  &
                         TRIM(TrimSigDigits(SurfaceNumAlpha)))
    ErrorsFound=.true.
  ENDIF
  NeedToAddSurfaces=0

  DO Loop=1,TotHTSubs
    CALL GetObjectItem(cCurrentModuleObject,Loop,cAlphaArgs,SurfaceNumAlpha,rNumericArgs,SurfaceNumProp,IOSTAT,  &
                   AlphaBlank=lAlphaFieldBlanks,NumBlank=lNumericFieldBlanks,  &
                   AlphaFieldnames=cAlphaFieldNames,NumericFieldNames=cNumericFieldNames)
    ErrorInName=.false.
    IsBlank=.false.
    CALL VerifyName(cAlphaArgs(1),SurfaceTmp%Name,SurfNum,ErrorInName,IsBlank,TRIM(cCurrentModuleObject)//' Name')
    IF (ErrorInName) THEN
      CALL ShowContinueError('...each surface name must not duplicate other surface names (of any type)')
      ErrorsFound=.true.
      CYCLE
    ENDIF

    IF (SurfaceNumProp < 12) THEN
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                      '", Too few number of numeric args=['//TRIM(TrimSigDigits(SurfaceNumProp))//'].')
      ErrorsFound=.true.
    ENDIF

    SurfNum=SurfNum+1
    SurfaceTmp(SurfNum)%Name = cAlphaArgs(1)  ! Set the Surface Name in the Derived Type
    ValidChk=FindItemInList(cAlphaArgs(2),SubSurfCls,6)
    IF (ValidChk == 0) THEN
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                             '", invalid '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2)))
      ErrorsFound=.true.
    ELSE
      SurfaceTmp(SurfNum)%Class = SubSurfIDs(ValidChk) ! Set class number
    ENDIF

    SurfaceTmp(SurfNum)%Construction=FindIteminList(cAlphaArgs(3),Construct%Name,TotConstructs)

    IF(SurfaceTmp(SurfNum)%Construction == 0) THEN
      ErrorsFound = .true.
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                             '", invalid '//TRIM(cAlphaFieldNames(3))//'="'//TRIM(cAlphaArgs(3))//'".')
    ELSE
      Construct(SurfaceTmp(SurfNum)%Construction)%IsUsed=.true.
      SurfaceTmp(SurfNum)%ConstructionStoredInputValue  = SurfaceTmp(SurfNum)%Construction
    END IF

    IF(SurfaceTmp(SurfNum)%Class.EQ.SurfaceClass_Window.OR.SurfaceTmp(SurfNum)%Class.EQ.SurfaceClass_GlassDoor &
      .OR.SurfaceTmp(SurfNum)%Class.EQ.SurfaceClass_TDD_Diffuser.OR.SurfaceTmp(SurfNum)%Class.EQ.SurfaceClass_TDD_Dome) THEN

      IF (SurfaceTmp(SurfNum)%Construction /= 0) THEN
        IF (.NOT.Construct(SurfaceTmp(SurfNum)%Construction)%TypeIsWindow) THEN
          ErrorsFound = .true.
          CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                 '" has an opaque surface construction; it should have a window construction.')
        ENDIF
      ENDIF

    ELSEIF (SurfaceTmp(SurfNum)%Construction /= 0) THEN
      IF (Construct(SurfaceTmp(SurfNum)%Construction)%TypeIsWindow) THEN
        ErrorsFound = .true.
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                               '", invalid '//TRIM(cAlphaFieldNames(3))//'="'//TRIM(cAlphaArgs(3))//  &
                               '" - has Window materials.')
        CALL ShowContinueError('...because '//TRIM(cAlphaFieldNames(2))//'='//TRIM(cAlphaArgs(2)))
      ENDIF
    ENDIF

    SurfaceTmp(SurfNum)%HeatTransSurf=.true.

    SurfaceTmp(SurfNum)%BaseSurfName=cAlphaArgs(4)
    !  The subsurface inherits properties from the base surface
    !  Exterior conditions, Zone, etc.
    !  We can figure out the base surface though, because they've all been entered
    Found=FindIteminList(SurfaceTmp(SurfNum)%BaseSurfName,SurfaceTmp%Name,TotSurfaces)
    IF (Found > 0) THEN
      SurfaceTmp(SurfNum)%BaseSurf=Found
      SurfaceTmp(SurfNum)%ExtBoundCond=SurfaceTmp(Found)%ExtBoundCond
      SurfaceTmp(SurfNum)%ExtBoundCondName=SurfaceTmp(Found)%ExtBoundCondName
      SurfaceTmp(SurfNum)%ExtSolar=SurfaceTmp(Found)%ExtSolar
      SurfaceTmp(SurfNum)%ExtWind=SurfaceTmp(Found)%ExtWind
      SurfaceTmp(SurfNum)%Zone=SurfaceTmp(Found)%Zone
      SurfaceTmp(SurfNum)%ZoneName=SurfaceTmp(Found)%ZoneName
      SurfaceTmp(SurfNum)%OSCPtr=SurfaceTmp(Found)%OSCPtr
      IF (SurfaceTmp(Found)%ExtBoundCond == UnreconciledZoneSurface .and.   &
          SurfaceTmp(Found)%ExtBoundCondName == SurfaceTmp(Found)%Name) THEN   ! Adiabatic surface, no windows or doors allowed
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                               '", invalid '//TRIM(cAlphaFieldNames(4))//'="'//TRIM(cAlphaArgs(4))//'".')
        CALL ShowContinueError('... adiabatic surfaces cannot have windows or doors.')
        CALL ShowContinueError('... no solar transmission will result for these windows or doors. '//  &
          'You must have interior windows or doors on Interzone surfaces for transmission to result.')
      ENDIF
    ELSE
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                             '", invalid '//TRIM(cAlphaFieldNames(4))//'="'//TRIM(cAlphaArgs(4)))
      SurfaceTmp(SurfNum)%ZoneName='Unknown Zone'
      ErrorsFound=.true.
    ENDIF

    IF (SurfaceTmp(SurfNum)%Class.EQ.SurfaceClass_TDD_Dome.OR.SurfaceTmp(SurfNum)%Class.EQ.SurfaceClass_TDD_Diffuser) THEN
      SurfaceTmp(SurfNum)%ExtBoundCond = ExternalEnvironment
    END IF

    IF (SurfaceTmp(SurfNum)%ExtBoundCond == ExternalEnvironment) THEN
      IF (.not. lAlphaFieldBlanks(5)) THEN
        CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                             '", invalid field '//TRIM(cAlphaFieldNames(5)))
        CALL ShowContinueError('...when Base surface uses "Outdoors" as '//trim(cAlphaFieldNames(5))//  &
           ', subsurfaces need to be blank to inherit the outdoor characteristics.')
        CALL ShowContinueError('...Surface external characteristics changed to reflect base surface.')
      ENDIF
    ENDIF

    IF (SurfaceTmp(SurfNum)%ExtBoundCond == UnreconciledZoneSurface) THEN ! "Surface" Base Surface
      IF (.not. lAlphaFieldBlanks(5)) THEN
        SurfaceTmp(SurfNum)%ExtBoundCondName=cAlphaArgs(5)
      ELSE
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                             '", invalid blank '//TRIM(cAlphaFieldNames(5)))
        CALL ShowContinueError('...when Base surface uses "Surface" as '//trim(cAlphaFieldNames(5))//  &
           ', subsurfaces must also specify specific surfaces in the adjacent zone.')
        SurfaceTmp(SurfNum)%ExtBoundCondName=cAlphaArgs(5)  ! putting it as blank will not confuse things later.
        ErrorsFound=.true.
      ENDIF
    ENDIF

    IF (SurfaceTmp(SurfNum)%ExtBoundCond == UnenteredAdjacentZoneSurface) THEN ! "Zone" - unmatched interior surface
      NeedToAddSurfaces=NeedToAddSurfaces+1
      ! ignoring window5datafiles for now -- will need to add.
    ENDIF

    IF (SurfaceTmp(SurfNum)%ExtBoundCond == OtherSideCoefNoCalcExt .or.   &
        SurfaceTmp(SurfNum)%ExtBoundCond == OtherSideCoefCalcExt) THEN
        IF (.not. lAlphaFieldBlanks(5)) THEN  ! Otherside Coef special Name
          Found=FindItemInList(cAlphaArgs(5),OSC%Name,TotOSC)
          IF (Found == 0) THEN
            CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                          '", invalid '//TRIM(cAlphaFieldNames(5))//'="'//TRIM(cAlphaArgs(5))//'".')
            CALL ShowContinueError('...base surface requires that this subsurface have OtherSideCoefficients -- not found.')
            ErrorsFound=.true.
          ELSE  ! found
            ! The following allows for a subsurface that has different characteristics than
            ! the base surface with OtherSide Coeff -- do we want that or is it an error?
            SurfaceTmp(SurfNum)%OSCPtr=Found
            SurfaceTmp(SurfNum)%ExtBoundCondName=cAlphaArgs(5)
            IF (OSC(Found)%SurfFilmCoef > 0.0d0) THEN
              SurfaceTmp(SurfNum)%ExtBoundCond=OtherSideCoefCalcExt
            ELSE
              SurfaceTmp(SurfNum)%ExtBoundCond = OtherSideCoefNoCalcExt
            ENDIF
          ENDIF
        ENDIF
    ENDIF

    IF (SurfaceTmp(SurfNum)%ExtBoundCond == OtherSideCondModeledExt) THEN
        SurfaceTmp(SurfNum)%ExtBoundCond = ExternalEnvironment
    ENDIF

    IF (SurfaceTmp(SurfNum)%ExtBoundCondName == Blank) THEN
      SurfaceTmp(SurfNum)%ExtBoundCondName=SurfaceTmp(SurfNum)%Name
    ENDIF
    SurfaceTmp(SurfNum)%ViewFactorGround = rNumericArgs(1)
    IF (lNumericFieldBlanks(1)) SurfaceTmp(SurfNum)%ViewFactorGround = AutoCalculate

    IF (lNumericFieldBlanks(3) .or. rNumericArgs(3) == AutoCalculate) THEN
      rNumericArgs(3)=(SurfaceNumProp-3)/3
      SurfaceTmp(SurfNum)%Sides=rNumericArgs(3)
      IF (MOD(SurfaceNumProp-3,3) /= 0) THEN
        CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                             '", '//TRIM(cNumericFieldNames(3))//          &
                              ' not even multiple of 3. Will read in '//   &
                              TRIM(TrimSigDigits(SurfaceTmp(SurfNum)%Sides)))
      ENDIF
      IF (rNumericArgs(3) < 3) THEN
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                             '", '//TRIM(cNumericFieldNames(3))//' (autocalculate) must be >= 3. Only '//  &
                             TRIM(TrimSigDigits(SurfaceTmp(SurfNum)%Sides))//' provided.')
        ErrorsFound=.true.
        CYCLE
      ENDIF
    ELSE
      numSides=(SurfaceNumProp-2)/3
      SurfaceTmp(SurfNum)%Sides=rNumericArgs(3)
      IF (numSides > SurfaceTmp(SurfNum)%Sides) THEN
        CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                  '", field '//TRIM(cNumericFieldNames(3))//'='//TRIM(TrimSigDigits(SurfaceTmp(SurfNum)%Sides)))
        CALL ShowContinueError('...but '//TRIM(TrimSigDigits(numSides))//' were entered. Only the indicated '//  &
                        TRIM(cNumericFieldNames(3))//' will be used.')
      ENDIF
    ENDIF
    ALLOCATE(SurfaceTmp(SurfNum)%Vertex(SurfaceTmp(SurfNum)%Sides))
    IF(SurfaceTmp(SurfNum)%Class.EQ.SurfaceClass_Window .or. SurfaceTmp(SurfNum)%Class.EQ.SurfaceClass_GlassDoor .or.  &
       SurfaceTmp(SurfNum)%Class.EQ.SurfaceClass_Door) &
      SurfaceTmp(SurfNum)%Multiplier = INT(rNumericArgs(2))
    ! Only windows, glass doors and doors can have Multiplier > 1:
    IF ( (SurfaceTmp(SurfNum)%Class .NE. SurfaceClass_Window .and. SurfaceTmp(SurfNum)%Class .ne. SurfaceClass_GlassDoor .and.  &
          SurfaceTmp(SurfNum)%Class .NE. SurfaceClass_Door) .AND. rNumericArgs(2) > 1.0d0) THEN
      CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                          '", invalid '//TRIM(cNumericFieldNames(2))//'=['//TRIM(TrimSigDigits(rNumericArgs(2),1))//'].')
      CALL ShowContinueError('...because '//TRIM(cAlphaFieldNames(2))//'='//TRIM(cAlphaArgs(2))//   &
      ' multiplier will be set to 1.0.')
      SurfaceTmp(SurfNum)%Multiplier = 1.0d0
    END IF

    CALL GetVertices(SurfNum,SurfaceTmp(SurfNum)%Sides,rNumericArgs(4:))

    CALL CheckConvexity(SurfNum,SurfaceTmp(SurfNum)%Sides)
    SurfaceTmp(SurfNum)%WindowShadingControlPtr = 0

    IF(SurfaceTmp(SurfNum)%Class.EQ.SurfaceClass_Window.OR.SurfaceTmp(SurfNum)%Class.EQ.SurfaceClass_GlassDoor &
      .OR.SurfaceTmp(SurfNum)%Class.EQ.SurfaceClass_TDD_Diffuser.OR.SurfaceTmp(SurfNum)%Class.EQ.SurfaceClass_TDD_Dome) THEN

      IF (SurfaceTmp(SurfNum)%ExtBoundCond == OtherSideCoefNoCalcExt .or.   &
          SurfaceTmp(SurfNum)%ExtBoundCond == OtherSideCoefCalcExt) THEN
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
            '", Other side coefficients are not allowed with windows.')
        ErrorsFound=.true.
      END IF

      IF (SurfaceTmp(SurfNum)%ExtBoundCond == Ground) THEN
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
            '", Exterior boundary condition = Ground is not be allowed with windows.')
        ErrorsFound=.true.
      END IF

      IF (cAlphaArgs(6) /= Blank) THEN
        IF (TotWinShadingControl > 0) THEN
          SurfaceTmp(SurfNum)%WindowShadingControlPtr = &
            FindIteminList(cAlphaArgs(6),WindowShadingControl%Name,TotWinShadingControl)
        ENDIF
        IF(SurfaceTmp(SurfNum)%WindowShadingControlPtr == 0) THEN
          CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                           '", invalid '//TRIM(cAlphaFieldNames(6))//'="'//TRIM(cAlphaArgs(6))//'".')
          ErrorsFound=.true.
        END IF


        ! Error if this is not an exterior window and shading device has been specified
        ! PETER: should doors be disallowed too?
        IF (SurfaceTmp(SurfNum)%WindowShadingControlPtr > 0 .AND. &
            SurfaceTmp(SurfNum)%ExtBoundCond /= ExternalEnvironment) THEN

          CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                           '", invalid '//TRIM(cAlphaFieldNames(6))//' because it is not an exterior window.')
          ErrorsFound=.true.

        ELSEIF (Construct(SurfaceTmp(SurfNum)%Construction)%WindowTypeEQL .AND. &
                SurfaceTmp(SurfNum)%WindowShadingControlPtr > 0) THEN

          CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                           '", invalid '//TRIM(cAlphaFieldNames(6))//'="'//TRIM(cAlphaArgs(6))//'".')
          CALL ShowContinueError('.. equivalent layer window model does not use shading control object.')
          CALL ShowContinueError('.. Shading control is set to none or zero, and simulation continues.')
          SurfaceTmp(SurfNum)%WindowShadingControlPtr = 0
        END IF
      END IF

      CALL CheckWindowShadingControlFrameDivider('GetHTSubSurfaceData',ErrorsFound,SurfNum,7)

      IF(SurfaceTmp(SurfNum)%Sides == 3) THEN  ! Triangular window
        IF(cAlphaArgs(7) /= Blank) THEN
          CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                           '", invalid '//TRIM(cAlphaFieldNames(7))//'="'//TRIM(cAlphaArgs(7))//'".')
          CALL ShowContinueError('.. because it is a triangular window and cannot have a frame or divider or reveal reflection.')
          CALL ShowContinueError('Frame, divider and reveal reflection will be ignored for this window.')
        END IF
        SurfaceTmp(SurfNum)%FrameDivider = 0
      END IF  ! End of check if window is triangular or rectangular

    END IF  ! check on non-opaquedoor subsurfaces

    CALL CheckSubSurfaceMiscellaneous('GetHTSubSurfaceData',ErrorsFound,SurfNum,cAlphaArgs(1),cAlphaArgs(3),AddedSubSurfaces)

  ENDDO  ! End of main loop over subsurfaces

  RETURN

END SUBROUTINE GetHTSubSurfaceData

SUBROUTINE GetRectSubSurfaces(ErrorsFound,SurfNum,TotWindows,TotDoors,TotGlazedDoors, &
                               TotIZWindows,TotIZDoors,TotIZGlazedDoors, &
                               SubSurfIDs,AddedSubSurfaces,NeedToAddSubSurfaces)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Linda Lawrie
          !       DATE WRITTEN   December 2008
          !       MODIFIED       na
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! Get simple (rectangular, relative origin to base surface) windows, doors, glazed doors.

          ! METHODOLOGY EMPLOYED:
          ! na

          ! REFERENCES:
          ! na

          ! USE STATEMENTS:
  USE DataIPShortCuts
  USE InputProcessor, ONLY: GetNumObjectsFound, GetObjectItem, FindItemInList, VerifyName, GetObjectDefMaxArgs
  USE General, ONLY: TrimSigDigits,RoundSigDigits

  IMPLICIT NONE ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
  LOGICAL, INTENT(INOUT)         :: ErrorsFound       ! Error flag indicator (true if errors found)
  INTEGER, INTENT(INOUT)         :: SurfNum           ! Count of Current SurfaceNumber
  INTEGER, INTENT(IN)            :: TotWindows        ! Number of Window SubSurfaces to obtain
  INTEGER, INTENT(IN)            :: TotDoors          ! Number of Door SubSurfaces to obtain
  INTEGER, INTENT(IN)            :: TotGlazedDoors    ! Number of Glass Door SubSurfaces to obtain
  INTEGER, INTENT(IN)            :: TotIZWindows      ! Number of Interzone Window SubSurfaces to obtain
  INTEGER, INTENT(IN)            :: TotIZDoors        ! Number of Interzone Door SubSurfaces to obtain
  INTEGER, INTENT(IN)            :: TotIZGlazedDoors  ! Number of Interzone Glass Door SubSurfaces to obtain
  INTEGER, DIMENSION(:), INTENT(IN) :: SubSurfIDs     ! ID Assignments for valid sub surface classes
  INTEGER, INTENT(INOUT)         :: AddedSubSurfaces  ! Subsurfaces added when windows reference Window5
                                                      !  data file entry with two glazing systems
  INTEGER, INTENT(INOUT)         :: NeedToAddSubSurfaces ! Number of surfaces to add, based on unentered IZ surfaces

          ! SUBROUTINE PARAMETER DEFINITIONS:
  CHARACTER(len=*), PARAMETER, DIMENSION(6) :: cModuleObjects=  &
    (/'Window              ',  &
      'Door                ',  &
      'GlazedDoor          ',  &
      'Window:Interzone    ',  &
      'Door:Interzone      ',  &
      'GlazedDoor:Interzone'/)

          ! INTERFACE BLOCK SPECIFICATIONS:
          ! na

          ! DERIVED TYPE DEFINITIONS:
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
  INTEGER :: Item
  INTEGER :: ItemsToGet
  INTEGER :: Loop
  INTEGER :: NumAlphas
  INTEGER :: NumNumbers
  INTEGER :: IOStat            ! IO Status when calling get input subroutine
  INTEGER :: Found             ! For matching base surfaces
  LOGICAL :: ErrorInName
  LOGICAL :: IsBlank
  LOGICAL :: GettingIZSurfaces
  INTEGER :: WindowShadingField
  INTEGER :: FrameField
  INTEGER :: OtherSurfaceField
  INTEGER :: ClassItem
  INTEGER :: IZFound

  DO Item=1,6

    cCurrentModuleObject=cModuleObjects(Item)
    IF (Item == 1) THEN
      ItemsToGet=TotWindows
      GettingIZSurfaces=.false.
      WindowShadingField=4
      FrameField=5
      OtherSurfaceField=0
      ClassItem=1
    ELSEIF (Item == 2) THEN
      ItemsToGet=TotDoors
      GettingIZSurfaces=.false.
      WindowShadingField=0
      FrameField=0
      OtherSurfaceField=0
      ClassItem=2
    ELSEIF (Item == 3) THEN
      ItemsToGet=TotGlazedDoors
      GettingIZSurfaces=.false.
      WindowShadingField=4
      FrameField=5
      OtherSurfaceField=0
      ClassItem=3
    ELSEIF (Item == 4) THEN
      ItemsToGet=TotIZWindows
      GettingIZSurfaces=.true.
      WindowShadingField=0
      FrameField=0
      OtherSurfaceField=4
      ClassItem=1
    ELSEIF (Item == 5) THEN
      ItemsToGet=TotIZDoors
      GettingIZSurfaces=.true.
      WindowShadingField=0
      FrameField=0
      OtherSurfaceField=4
      ClassItem=2
    ELSE  ! Item = 6
      ItemsToGet=TotIZGlazedDoors
      GettingIZSurfaces=.true.
      WindowShadingField=0
      FrameField=0
      OtherSurfaceField=4
      ClassItem=3
    ENDIF

    DO Loop=1,ItemsToGet
      CALL GetObjectItem(cCurrentModuleObject,Loop,cAlphaArgs,NumAlphas,rNumericArgs,NumNumbers,IOSTAT,  &
                     AlphaBlank=lAlphaFieldBlanks,NumBlank=lNumericFieldBlanks,  &
                     AlphaFieldnames=cAlphaFieldNames,NumericFieldNames=cNumericFieldNames)
      ErrorInName=.false.
      IsBlank=.false.
      CALL VerifyName(cAlphaArgs(1),SurfaceTmp%Name,SurfNum,ErrorInName,IsBlank,TRIM(cCurrentModuleObject)//' Name')
      IF (ErrorInName) THEN
        CALL ShowContinueError('...each surface name must not duplicate other surface names (of any type)')
        ErrorsFound=.true.
        CYCLE
      ENDIF

      IF (NumNumbers < 5) THEN
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(cAlphaArgs(1))//  &
                        '", Too few number of numeric args=['//TRIM(TrimSigDigits(NumNumbers))//'].')
        ErrorsFound=.true.
      ENDIF

      SurfNum=SurfNum+1
      SurfaceTmp(SurfNum)%Name = cAlphaArgs(1)  ! Set the Surface Name in the Derived Type
      SurfaceTmp(SurfNum)%Class = SubSurfIDs(ClassItem) ! Set class number

      SurfaceTmp(SurfNum)%Construction=FindIteminList(cAlphaArgs(2),Construct%Name,TotConstructs)

      IF(SurfaceTmp(SurfNum)%Construction == 0) THEN
        ErrorsFound = .true.
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                               '", invalid '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))//'".')
      ELSE
        Construct(SurfaceTmp(SurfNum)%Construction)%IsUsed=.true.
        SurfaceTmp(SurfNum)%ConstructionStoredInputValue  = SurfaceTmp(SurfNum)%Construction
      END IF

      IF(SurfaceTmp(SurfNum)%Class.EQ.SurfaceClass_Window.OR.SurfaceTmp(SurfNum)%Class.EQ.SurfaceClass_GlassDoor) THEN

        IF (SurfaceTmp(SurfNum)%Construction /= 0) THEN
          IF (.NOT.Construct(SurfaceTmp(SurfNum)%Construction)%TypeIsWindow) THEN
            ErrorsFound = .true.
            CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                   '" has an opaque surface construction; it should have a window construction.')
          ENDIF
        ENDIF

      ELSEIF (SurfaceTmp(SurfNum)%Construction /= 0) THEN
        IF (Construct(SurfaceTmp(SurfNum)%Construction)%TypeIsWindow) THEN
          ErrorsFound = .true.
          CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                                 '", invalid '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))//  &
                                 '" - has Window materials.')
        ENDIF
      ENDIF

      SurfaceTmp(SurfNum)%HeatTransSurf=.true.

      SurfaceTmp(SurfNum)%BaseSurfName=cAlphaArgs(3)
      !  The subsurface inherits properties from the base surface
      !  Exterior conditions, Zone, etc.
      !  We can figure out the base surface though, because they've all been entered
      Found=FindIteminList(SurfaceTmp(SurfNum)%BaseSurfName,SurfaceTmp%Name,TotSurfaces)
      IF (Found > 0) THEN
        SurfaceTmp(SurfNum)%BaseSurf=Found
        SurfaceTmp(SurfNum)%ExtBoundCond=SurfaceTmp(Found)%ExtBoundCond
        SurfaceTmp(SurfNum)%ExtBoundCondName=SurfaceTmp(Found)%ExtBoundCondName
        SurfaceTmp(SurfNum)%ExtSolar=SurfaceTmp(Found)%ExtSolar
        SurfaceTmp(SurfNum)%ExtWind=SurfaceTmp(Found)%ExtWind
        SurfaceTmp(SurfNum)%Tilt=SurfaceTmp(Found)%Tilt
        SurfaceTmp(SurfNum)%Azimuth=SurfaceTmp(Found)%Azimuth
        SurfaceTmp(SurfNum)%Zone=SurfaceTmp(Found)%Zone
        SurfaceTmp(SurfNum)%ZoneName=SurfaceTmp(Found)%ZoneName
        SurfaceTmp(SurfNum)%OSCPtr=SurfaceTmp(Found)%OSCPtr
        SurfaceTmp(SurfNum)%ViewFactorGround = SurfaceTmp(Found)%ViewFactorGround
        SurfaceTmp(SurfNum)%ViewFactorSky = SurfaceTmp(Found)%ViewFactorSky
      ELSE
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                               '", invalid '//TRIM(cAlphaFieldNames(3))//'="'//TRIM(cAlphaArgs(3)))
        SurfaceTmp(SurfNum)%ZoneName='Unknown Zone'
        ErrorsFound=.true.
        CYCLE
      ENDIF
      IF (SurfaceTmp(Found)%ExtBoundCond == UnreconciledZoneSurface .and.  &
          SurfaceTmp(Found)%ExtBoundCondName == SurfaceTmp(Found)%Name) THEN   ! Adiabatic surface, no windows or doors allowed
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                               '", invalid '//TRIM(cAlphaFieldNames(3))//'="'//TRIM(cAlphaArgs(3))//'".')
        CALL ShowContinueError('... adiabatic surfaces cannot have windows or doors.')
        CALL ShowContinueError('... no solar transmission will result for these windows or doors. '//  &
          'You must have interior windows or doors on Interzone surfaces for transmission to result.')
      ENDIF

      IF (SurfaceTmp(SurfNum)%ExtBoundCond == UnreconciledZoneSurface) THEN ! "Surface" Base Surface
        IF (.not. GettingIZSurfaces) THEN
          CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                               '", invalid use of object')
          CALL ShowContinueError('...when Base surface uses "Surface" as '//trim(cAlphaFieldNames(5))//  &
             ', subsurfaces must also specify specific surfaces in the adjacent zone.')
          CALL ShowContinueError('...Please use '//trim(cCurrentModuleObject)//':Interzone to enter this surface.')
          SurfaceTmp(SurfNum)%ExtBoundCondName=blank  ! putting it as blank will not confuse things later.
          ErrorsFound=.true.
        ENDIF
      ENDIF

      IF (SurfaceTmp(SurfNum)%ExtBoundCond == UnreconciledZoneSurface) THEN ! "Surface" Base Surface
        IF (GettingIZSurfaces) THEN
          SurfaceTmp(SurfNum)%ExtBoundCondName=cAlphaArgs(OtherSurfaceField)
          IZFound=FindItemInList(SurfaceTmp(SurfNum)%ExtBoundCondName,Zone%Name,NumOfZones)
          IF (IZFound > 0) SurfaceTmp(SurfNum)%ExtBoundCond=UnenteredAdjacentZoneSurface
        ELSE  ! Interior Window
          SurfaceTmp(SurfNum)%ExtBoundCondName=SurfaceTmp(SurfNum)%Name
        ENDIF
      ENDIF

      ! This is the parent's property:
      IF (SurfaceTmp(SurfNum)%ExtBoundCond == UnenteredAdjacentZoneSurface) THEN ! OtherZone - unmatched interior surface
        IF (GettingIZSurfaces) THEN
          NeedToAddSubSurfaces=NeedToAddSubSurfaces+1
        ELSE  ! Interior Window
          CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                               '", invalid Interzone Surface, specify '//trim(cCurrentModuleObject)//':InterZone')
          CALL ShowContinueError('...when base surface is an interzone surface, subsurface must also be an interzone surface.')
          NeedToAddSubSurfaces=NeedToAddSubSurfaces+1
          ErrorsFound=.true.
        ENDIF
      ENDIF

      IF (GettingIZSurfaces) THEN
        IF (lAlphaFieldBlanks(OtherSurfaceField)) THEN
          ! blank -- set it up for unentered adjacent zone
          IF (SurfaceTmp(SurfNum)%ExtBoundCond == UnenteredAdjacentZoneSurface) THEN  ! already set but need Zone
            SurfaceTmp(SurfNum)%ExtBoundCondName=SurfaceTmp(Found)%ExtBoundCondName  ! base surface has it
          ELSEIF (SurfaceTmp(SurfNum)%ExtBoundCond == UnreconciledZoneSurface) THEN
            SurfaceTmp(SurfNum)%ExtBoundCondName=SurfaceTmp(Found)%ZoneName  ! base surface has it
            SurfaceTmp(SurfNum)%ExtBoundCond=UnenteredAdjacentZoneSurface
          ELSE  ! not correct boundary condition for interzone subsurface
            CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                                 '", invalid Base Surface type for Interzone Surface')
            CALL ShowContinueError('...when base surface is not an interzone surface, '//  &
               'subsurface must also not be an interzone surface.')
            ErrorsFound=.true.
          ENDIF
        ENDIF
      ENDIF

      IF (SurfaceTmp(SurfNum)%ExtBoundCond == OtherSideCondModeledExt) THEN
          SurfaceTmp(SurfNum)%ExtBoundCond = ExternalEnvironment
      ENDIF

!      SurfaceTmp(SurfNum)%ViewFactorGround = AutoCalculate

      SurfaceTmp(SurfNum)%Sides=4
      ALLOCATE(SurfaceTmp(SurfNum)%Vertex(SurfaceTmp(SurfNum)%Sides))
      IF(SurfaceTmp(SurfNum)%Class.EQ.SurfaceClass_Window .or. SurfaceTmp(SurfNum)%Class.EQ.SurfaceClass_GlassDoor .or.  &
         SurfaceTmp(SurfNum)%Class.EQ.SurfaceClass_Door) &
        SurfaceTmp(SurfNum)%Multiplier = INT(rNumericArgs(1))
      ! Only windows, glass doors and doors can have Multiplier > 1:
      IF ( (SurfaceTmp(SurfNum)%Class .NE. SurfaceClass_Window .and. SurfaceTmp(SurfNum)%Class .ne. SurfaceClass_GlassDoor .and.  &
            SurfaceTmp(SurfNum)%Class .NE. SurfaceClass_Door) .AND. rNumericArgs(1) > 1.0d0) THEN
        CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                            '", invalid '//TRIM(cNumericFieldNames(1))//'=['//TRIM(TrimSigDigits(rNumericArgs(1),1))//'].')
        CALL ShowContinueError('...because '//TRIM(cAlphaFieldNames(1))//'='//TRIM(cAlphaArgs(1))//   &
        ' multiplier will be set to 1.0.')
        SurfaceTmp(SurfNum)%Multiplier = 1.0d0
      END IF

      CALL MakeRelativeRectangularVertices(SurfaceTmp(SurfNum)%BaseSurf,SurfNum,  &
                         rNumericArgs(2),rNumericArgs(3),rNumericArgs(4),rNumericArgs(5))

      IF (SurfaceTmp(SurfNum)%Area <= 0.0d0) THEN
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
              '", Surface Area <= 0.0; Entered Area='//  &
              TRIM(TrimSigDigits(SurfaceTmp(SurfNum)%Area,2)))
        ErrorsFound=.true.
      ENDIF

      SurfaceTmp(SurfNum)%WindowShadingControlPtr = 0

      IF(.not. GettingIZSurfaces .and. &
          (SurfaceTmp(SurfNum)%Class.EQ.SurfaceClass_Window.OR.SurfaceTmp(SurfNum)%Class.EQ.SurfaceClass_GlassDoor)) THEN

        IF (SurfaceTmp(SurfNum)%ExtBoundCond == OtherSideCoefNoCalcExt .or.   &
            SurfaceTmp(SurfNum)%ExtBoundCond == OtherSideCoefCalcExt) THEN
          CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
              '", Other side coefficients are not allowed with windows.')
          ErrorsFound=.true.
        END IF

        IF (SurfaceTmp(SurfNum)%ExtBoundCond == Ground) THEN
          CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
              '", Exterior boundary condition = Ground is not be allowed with windows.')
          ErrorsFound=.true.
        END IF

        IF (cAlphaArgs(WindowShadingField) /= Blank) THEN
          IF (TotWinShadingControl > 0) THEN
            SurfaceTmp(SurfNum)%WindowShadingControlPtr = &
              FindIteminList(cAlphaArgs(WindowShadingField),WindowShadingControl%Name,TotWinShadingControl)
          ENDIF
          IF(SurfaceTmp(SurfNum)%WindowShadingControlPtr == 0) THEN
            CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                   '", invalid '//TRIM(cAlphaFieldNames(WindowShadingField))//'="'//TRIM(cAlphaArgs(WindowShadingField))//'".')
            ErrorsFound=.true.
          END IF


          ! Error if this is not an exterior window and shading device has been specified
          ! PETER: should doors be disallowed too?
          IF (SurfaceTmp(SurfNum)%WindowShadingControlPtr > 0 .AND. &
              SurfaceTmp(SurfNum)%ExtBoundCond /= ExternalEnvironment) THEN

            CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                   '", invalid '//TRIM(cAlphaFieldNames(WindowShadingField))//' because it is not an exterior window.')
            ErrorsFound=.true.
          END IF
        END IF

        CALL CheckWindowShadingControlFrameDivider('GetRectSubSurfaces',ErrorsFound,SurfNum,FrameField)

      END IF  ! check on non-opaquedoor subsurfaces

      CALL CheckSubSurfaceMiscellaneous('GetRectSubSurfaces',ErrorsFound,SurfNum,cAlphaArgs(1),cAlphaArgs(2),AddedSubSurfaces)

    ENDDO  ! Getting Items

  ENDDO

  RETURN

END SUBROUTINE GetRectSubSurfaces

SUBROUTINE CheckWindowShadingControlFrameDivider(cRoutineName,ErrorsFound,SurfNum,FrameField)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Linda Lawrie
          !       DATE WRITTEN   December 2008
          !       MODIFIED       na
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! This routine performs checks on WindowShadingControl settings and Frame/Divider Settings.

          ! METHODOLOGY EMPLOYED:
          ! na

          ! REFERENCES:
          ! na

          ! USE STATEMENTS:
  USE DataIPShortCuts
  USE InputProcessor, ONLY: FindItemInList
  USE General, ONLY: TrimSigDigits,RoundSigDigits

  IMPLICIT NONE ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
          ! na

          ! SUBROUTINE PARAMETER DEFINITIONS:
  CHARACTER(len=*), INTENT(IN) :: cRoutineName  ! routine name calling this one (for error messages)
  LOGICAL, INTENT(INOUT) :: ErrorsFound  ! true if errors have been found or are found here
  INTEGER, INTENT(IN)    :: SurfNum      ! current surface number
  INTEGER, INTENT(IN)    :: FrameField   ! field number for frame/divider

          ! INTERFACE BLOCK SPECIFICATIONS:
          ! na

          ! DERIVED TYPE DEFINITIONS:
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
  INTEGER :: WSCPtr       ! WindowShadingControl Index
  INTEGER :: ConstrNumSh  ! Construction number with Shade
  INTEGER :: ConstrNum    ! Construction number
  INTEGER :: ShDevNum     ! Shading Device number
  INTEGER :: Lay               ! Layer number
  INTEGER :: TotGlassLayers    ! Number of glass layers in window construction
  INTEGER :: TotLayers         ! Number of layers in unshaded construction
  INTEGER :: TotShLayers       ! Number of layers in shaded construction
  INTEGER :: MatGap            ! Gap material number
  INTEGER :: MatGap1           ! Material number of gap to left (outer side) of between-glass shade/blind
  INTEGER :: MatGap2           ! Material number of gap to right (inner side) of between-glass shade/blind
  INTEGER :: MatSh             ! Between-glass shade/blind material number
  REAL(r64) :: MatGapCalc      ! Calculated MatGap diff for shaded vs non-shaded constructions

  ! If WindowShadingControl has been specified for this window --
  ! Set shaded construction number if shaded construction was specified in WindowShadingControl.
  ! Otherwise, create shaded construction if WindowShadingControl for this window has
  ! interior or exterior shade/blind (but not between-glass shade/blind) specified.


  WSCptr = SurfaceTmp(SurfNum)%WindowShadingControlPtr
  ConstrNumSh=0
  IF(.NOT.ErrorsFound .AND. WSCptr > 0) THEN
    ConstrNumSh = WindowShadingControl(WSCptr)%ShadedConstruction
    IF(ConstrNumSh > 0) THEN
      SurfaceTmp(SurfNum)%ShadedConstruction = ConstrNumSh
    ELSE
      IF(WindowShadingControl(WSCptr)%ShadingType==WSC_ST_InteriorShade.OR. &
         WindowShadingControl(WSCptr)%ShadingType==WSC_ST_InteriorBlind.OR. &
         WindowShadingControl(WSCptr)%ShadingType==WSC_ST_ExteriorShade.OR. &
         WindowShadingControl(WSCptr)%ShadingType==WSC_ST_ExteriorScreen.OR. &
         WindowShadingControl(WSCptr)%ShadingType==WSC_ST_ExteriorBlind) THEN
        ShDevNum = WindowShadingControl(WSCptr)%ShadingDevice
        IF(ShDevNum > 0) THEN
          CALL CreateShadedWindowConstruction(SurfNum,WSCptr,ShDevNum)
          ConstrNumSh = SurfaceTmp(SurfNum)%ShadedConstruction
        ENDIF
      END IF
    END IF
  END IF

  ! Error checks for shades and blinds

  ConstrNum = SurfaceTmp(SurfNum)%Construction
  IF (.NOT.ErrorsFound .AND. WSCptr > 0 .AND. ConstrNum > 0 .AND. ConstrNumSh > 0) THEN

    IF(WindowShadingControl(WSCptr)%ShadingType==WSC_ST_InteriorShade.OR. &
       WindowShadingControl(WSCptr)%ShadingType==WSC_ST_InteriorBlind) THEN
      TotLayers = Construct(ConstrNum)%TotLayers
      TotShLayers = Construct(ConstrNumSh)%TotLayers
      IF (TotShLayers-1 /= TotLayers) THEN
        CALL ShowWarningError('WindowProperty:ShadingControl: Interior shade or blind: Potential problem in match of '//  &
                              'unshaded/shaded constructions, shaded should have 1 more layers than unshaded.')
        CALL ShowContinueError('Unshaded construction='//TRIM(Construct(ConstrNum)%Name))
        CALL ShowContinueError('Shaded construction='//TRIM(Construct(ConstrNumSh)%Name))
        CALL ShowContinueError('If preceding two constructions are same name, you have likely specified a '//   &
                               'WindowProperty:ShadingControl (Field #3) with the Window Construction rather than '//    &
                               'a shaded construction.')
      ENDIF
      DO Lay = 1,Construct(ConstrNum)%TotLayers
        IF(Construct(ConstrNum)%LayerPoint(Lay) /= Construct(ConstrNumSh)%LayerPoint(Lay)) THEN
          ErrorsFound = .TRUE.
          CALL ShowSevereError &
            (' The glass and gas layers in the shaded and unshaded constructions do not match for window=' &
              //TRIM(SurfaceTmp(SurfNum)%Name))
          CALL ShowContinueError('Unshaded construction='//TRIM(Construct(ConstrNum)%Name))
          CALL ShowContinueError('Shaded construction='//TRIM(Construct(ConstrNumSh)%Name))
          EXIT
        END IF
      END DO
    END IF

    IF(WindowShadingControl(WSCptr)%ShadingType==WSC_ST_ExteriorShade.OR. &
       WindowShadingControl(WSCptr)%ShadingType==WSC_ST_ExteriorScreen.OR. &
       WindowShadingControl(WSCptr)%ShadingType==WSC_ST_ExteriorBlind) THEN
      TotLayers = Construct(ConstrNum)%TotLayers
      TotShLayers = Construct(ConstrNumSh)%TotLayers
      IF (TotShLayers-1 /= TotLayers) THEN
        CALL ShowWarningError('WindowProperty:ShadingControl: Exterior shade, screen or blind: '//  &
           'Potential problem in match of unshaded/shaded constructions, shaded should have 1 more layer than unshaded.')
        CALL ShowContinueError('Unshaded construction='//TRIM(Construct(ConstrNum)%Name))
        CALL ShowContinueError('Shaded construction='//TRIM(Construct(ConstrNumSh)%Name))
        CALL ShowContinueError('If preceding two constructions have the same name, you have likely specified a '//   &
                               'WindowProperty:ShadingControl (Field #3) with the Window Construction rather than '//    &
                               'a shaded construction.')
      ENDIF
      DO Lay = 1,Construct(ConstrNum)%TotLayers
        IF(Construct(ConstrNum)%LayerPoint(Lay) /= Construct(ConstrNumSh)%LayerPoint(Lay+1)) THEN
          ErrorsFound = .TRUE.
          CALL ShowSevereError &
            (' The glass and gas layers in the shaded and unshaded constructions do not match for window=' &
              //TRIM(SurfaceTmp(SurfNum)%Name))
          CALL ShowContinueError('Unshaded construction='//TRIM(Construct(ConstrNum)%Name))
          CALL ShowContinueError('Shaded construction='//TRIM(Construct(ConstrNumSh)%Name))
          EXIT
        END IF
      END DO
    END IF

    IF(WindowShadingControl(WSCptr)%ShadingType==WSC_ST_BetweenGlassShade.OR. &
       WindowShadingControl(WSCptr)%ShadingType==WSC_ST_BetweenGlassBlind) THEN
          ! Divider not allowed with between-glass shade or blind
      IF(SurfaceTmp(SurfNum)%FrameDivider > 0) THEN
        IF(FrameDivider(SurfaceTmp(SurfNum)%FrameDivider)%DividerWidth > 0.0d0) THEN
          CALL ShowWarningError('A divider cannot be specified for window '//TRIM(SurfaceTmp(SurfNum)%Name))
          CALL ShowContinueError(', which has a between-glass shade or blind.')
          CALL ShowContinueError('Calculation will proceed without the divider for this window.')
          FrameDivider(SurfaceTmp(SurfNum)%FrameDivider)%DividerWidth = 0.0d0
        END IF
      END IF
          ! Check consistency of gap widths between unshaded and shaded constructions
      TotGlassLayers = Construct(ConstrNum)%TotGlassLayers
      TotLayers = Construct(ConstrNum)%TotLayers
      TotShLayers = Construct(ConstrNumSh)%TotLayers
      IF (TotShLayers-2 /= TotLayers) THEN
        CALL ShowWarningError('WindowProperty:ShadingControl: Between Glass Shade/Blind: Potential problem in match of '//  &
                              'unshaded/shaded constructions, shaded should have 2 more layers than unshaded.')
        CALL ShowContinueError('Unshaded construction='//TRIM(Construct(ConstrNum)%Name))
        CALL ShowContinueError('Shaded construction='//TRIM(Construct(ConstrNumSh)%Name))
        CALL ShowContinueError('If preceding two constructions are same name, you have likely specified a '//   &
                               'WindowProperty:ShadingControl (Field #3) with the Window Construction rather than '//    &
                               'a shaded construction.')
      ENDIF
      IF (Construct(ConstrNum)%LayerPoint(TotLayers) /= Construct(ConstrNumSh)%LayerPoint(TotShLayers)) THEN
        CALL ShowSevereError(trim(cRoutineName)//': Mis-match in unshaded/shaded inside layer materials.  These should match.')
        CALL ShowContinueError('Unshaded construction='//TRIM(Construct(ConstrNum)%Name)//  &
                 ', Material='//TRIM(Material(Construct(ConstrNum)%LayerPoint(TotLayers))%Name))
        CALL ShowContinueError('Shaded construction='//TRIM(Construct(ConstrNumSh)%Name)// &
                 ', Material='//TRIM(Material(Construct(ConstrNumSh)%LayerPoint(TotShLayers))%Name))
        ErrorsFound=.true.
      ENDIF
      IF (Construct(ConstrNum)%LayerPoint(1) /= Construct(ConstrNumSh)%LayerPoint(1)) THEN
        CALL ShowSevereError(trim(cRoutineName)//': Mis-match in unshaded/shaded inside layer materials.  These should match.')
        CALL ShowContinueError('Unshaded construction='//TRIM(Construct(ConstrNum)%Name)//  &
                 ', Material='//TRIM(Material(Construct(ConstrNum)%LayerPoint(1))%Name))
        CALL ShowContinueError('Shaded construction='//TRIM(Construct(ConstrNumSh)%Name)// &
                 ', Material='//TRIM(Material(Construct(ConstrNumSh)%LayerPoint(1))%Name))
        ErrorsFound=.true.
      ENDIF
      IF(TotGlassLayers == 2 .OR. TotGlassLayers == 3) THEN
        MatGap =  Construct(ConstrNum)%LayerPoint(2*TotGlassLayers-2)
        MatGap1 = Construct(ConstrNumSh)%LayerPoint(2*TotGlassLayers-2)
        MatGap2 = Construct(ConstrNumSh)%LayerPoint(2*TotGlassLayers)
        MatSh = Construct(ConstrNumSh)%LayerPoint(2*TotGlassLayers-1)
        IF(WindowShadingControl(WSCptr)%ShadingType==WSC_ST_BetweenGlassBlind) THEN
          MatGapCalc=ABS(Material(MatGap)%Thickness-(Material(MatGap1)%Thickness+Material(MatGap2)%Thickness))
          IF(MatGapCalc > 0.001d0) THEN
            CALL ShowSevereError(trim(cRoutineName)//': The gap width(s) for the unshaded window construction ' &
                  //TRIM(Construct(ConstrNum)%Name))
            CALL ShowContinueError('are inconsistent with the gap widths for shaded window construction ' &
                  //TRIM(Construct(ConstrNumSh)%Name))
            CALL ShowContinueError('for window '//TRIM(SurfaceTmp(SurfNum)%Name)//', which has a between-glass blind.')
            CALL ShowContinueError('..Material='//TRIM(Material(MatGap)%Name)//   &
                            ' thickness='//TRIM(RoundSigDigits(Material(MatGap)%Thickness,3))//' -')
            CALL ShowContinueError('..( Material='//TRIM(Material(MatGap1)%Name)//  &
                            ' thickness='//TRIM(RoundSigDigits(Material(MatGap1)%Thickness,3))//' +')
            CALL ShowContinueError('..Material='//TRIM(Material(MatGap2)%Name)//  &
                            ' thickness='//TRIM(RoundSigDigits(Material(MatGap2)%Thickness,3))//' )=['//  &
                            trim(RoundSigDigits(MatGapCalc,3))//'] >.001')
            ErrorsFound=.true.
          END IF
        ELSE  ! Between-glass shade
          MatGapCalc=ABS(Material(MatGap)%Thickness-  &
                         (Material(MatGap1)%Thickness+Material(MatGap2)%Thickness+Material(MatSh)%Thickness))
          IF(MatGapCalc > 0.001d0) THEN
            CALL ShowSevereError(trim(cRoutineName)//': The gap width(s) for the unshaded window construction ' &
                  //TRIM(Construct(ConstrNum)%Name))
            CALL ShowContinueError('are inconsistent with the gap widths for shaded window construction ' &
                  //TRIM(Construct(ConstrNumSh)%Name))
            CALL ShowContinueError('for window '//TRIM(SurfaceTmp(SurfNum)%Name)//', which has a between-glass shade.')
            CALL ShowContinueError('..Material='//TRIM(Material(MatGap)%Name)//  &
                            ' thickness='//TRIM(RoundSigDigits(Material(MatGap)%Thickness,3))//' -')
            CALL ShowContinueError('...( Material='//TRIM(Material(MatGap1)%Name)//  &
                            ' thickness='//TRIM(RoundSigDigits(Material(MatGap1)%Thickness,3))//' +')
            CALL ShowContinueError('..Material='//TRIM(Material(MatGap2)%Name)//  &
                            ' thickness='//TRIM(RoundSigDigits(Material(MatGap2)%Thickness,3))//' +')
            CALL ShowContinueError('..Material='//TRIM(Material(MatSh)%Name)//    &
                            ' thickness='//TRIM(RoundSigDigits(Material(MatSh)%Thickness,3))//' )=['//  &
                            trim(RoundSigDigits(MatGapCalc,3))//'] >.001')
            ErrorsFound=.true.
          END IF
        END IF
      END IF
    END IF
  END IF

  IF(SurfaceTmp(SurfNum)%Sides /= 3) THEN  ! Rectangular Window
    ! Initialize the FrameDivider number for this window. W5FrameDivider will be positive if
    ! this window's construction came from the Window5 data file and that construction had an
    ! associated frame or divider. It will be zero if the window's construction is not from the
    ! Window5 data file, or the construction is from the data file, but the construction has no
    ! associated frame or divider. Note that if there is a FrameDivider candidate for this
    ! window from the Window5 data file it is used instead of the window's input FrameDivider.

    IF(SurfaceTmp(SurfNum)%Construction /= 0) THEN
      SurfaceTmp(SurfNum)%FrameDivider = Construct(SurfaceTmp(SurfNum)%Construction)%W5FrameDivider

      ! Warning if FrameAndDivider for this window is over-ridden by one from Window5 Data File
      IF(SurfaceTmp(SurfNum)%FrameDivider > 0 .AND. .not. lAlphaFieldBlanks(FrameField)) THEN
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                       '", '//TRIM(cAlphaFieldNames(FrameField))//'="'//TRIM(cAlphaArgs(FrameField))//'"')
        CALL ShowContinueError('will be replaced with FrameAndDivider from Window5 Data File entry ' &
              //TRIM(Construct(SurfaceTmp(SurfNum)%Construction)%Name))
      END IF

      IF (.not. lAlphaFieldBlanks(FrameField) .AND. SurfaceTmp(SurfNum)%FrameDivider == 0) THEN
        SurfaceTmp(SurfNum)%FrameDivider = &
          FindIteminList(cAlphaArgs(FrameField),FrameDivider%Name,TotFrameDivider)
        IF(SurfaceTmp(SurfNum)%FrameDivider == 0) THEN
          IF (.NOT. Construct(SurfaceTmp(SurfNum)%Construction)%WindowTypeEQL) THEN
               CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                    '", invalid '//TRIM(cAlphaFieldNames(FrameField))//'="'//TRIM(cAlphaArgs(FrameField))//'"')
               ErrorsFound=.true.
          ELSE
               CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                   '", invalid '//TRIM(cAlphaFieldNames(FrameField))//'="'//TRIM(cAlphaArgs(FrameField))//'"')
               CALL ShowContinueError('...Frame/Divider is not supported in Equivalent Layer Window model.')
          ENDIF
        END IF
            ! Divider not allowed with between-glass shade or blind
        IF(.NOT.ErrorsFound .AND. WSCptr > 0 .AND. ConstrNumSh > 0) THEN
          IF(WindowShadingControl(WSCptr)%ShadingType==WSC_ST_BetweenGlassShade.OR. &
            WindowShadingControl(WSCptr)%ShadingType==WSC_ST_BetweenGlassBlind) THEN
            IF(SurfaceTmp(SurfNum)%FrameDivider > 0) THEN
              IF(FrameDivider(SurfaceTmp(SurfNum)%FrameDivider)%DividerWidth > 0.0d0) THEN
                CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                       '", invalid '//TRIM(cAlphaFieldNames(FrameField))//'="'//TRIM(cAlphaArgs(FrameField))//'"')
                CALL ShowContinueError('Divider cannot be specified because the construction has a between-glass shade or blind.')
                CALL ShowContinueError('Calculation will proceed without the divider for this window.')
                CALL ShowContinueError('Divider width = ['//  &
                   trim(RoundSigDigits(FrameDivider(SurfaceTmp(SurfNum)%FrameDivider)%DividerWidth,2))//'].')
                FrameDivider(SurfaceTmp(SurfNum)%FrameDivider)%DividerWidth = 0.0d0
              END IF
            END IF ! End of check if window has divider
          END IF  ! End of check if window has a between-glass shade or blind
        END IF  ! End of check if window has a shaded construction
      END IF  ! End of check if window has an associated FrameAndDivider
    END IF  ! End of check if window has a construction
  END IF

  IF (Construct(SurfaceTmp(SurfNum)%Construction)%WindowTypeEQL) THEN
     IF(SurfaceTmp(SurfNum)%FrameDivider > 0) THEN
        ! Equivalent Layer window does not have frame/divider model
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
             '", invalid '//TRIM(cAlphaFieldNames(FrameField))//'="'//TRIM(cAlphaArgs(FrameField))//'"')
        CALL ShowContinueError('Frame/Divider is not supported in Equivalent Layer Window model.')
        SurfaceTmp(SurfNum)%FrameDivider = 0
     ENDIF
  ENDIF

  RETURN

END SUBROUTINE CheckWindowShadingControlFrameDivider

SUBROUTINE CheckSubSurfaceMiscellaneous(cRoutineName,ErrorsFound,SurfNum,SubSurfaceName,SubSurfaceConstruction,AddedSubSurfaces)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Linda Lawrie
          !       DATE WRITTEN   December 2008
          !       MODIFIED       na
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! This routine performs miscellaneous checks on subsurfaces: Windows, GlassDoors, Doors, Tubular Devices.

          ! METHODOLOGY EMPLOYED:
          ! na

          ! REFERENCES:
          ! na

          ! USE STATEMENTS:
!  USE DataIPShortCuts
  USE InputProcessor, ONLY: FindItemInList
  USE General, ONLY: TrimSigDigits,RoundSigDigits
  USE DataErrorTracking

  IMPLICIT NONE ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
  CHARACTER(len=*), INTENT(IN) :: cRoutineName  ! routine name calling this one (for error messages)
  LOGICAL, INTENT(INOUT) :: ErrorsFound  ! true if errors have been found or are found here
  INTEGER, INTENT(IN)    :: SurfNum      ! current surface number
  CHARACTER(len=*), INTENT(IN)    :: SubSurfaceName    !  name of the surface
  CHARACTER(len=*), INTENT(IN)    :: SubSurfaceConstruction    !  name of the construction
  INTEGER, INTENT(INOUT) :: AddedSubSurfaces

          ! SUBROUTINE PARAMETER DEFINITIONS:
          ! na

          ! INTERFACE BLOCK SPECIFICATIONS:
          ! na

          ! DERIVED TYPE DEFINITIONS:
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
  INTEGER :: NumShades  ! count on number of shading layers
  INTEGER :: Lay               ! Layer number
  INTEGER :: LayerPtr          ! Layer pointer
  INTEGER :: ConstrNum    ! Construction number
  INTEGER :: Found        ! when item is found

  ! Warning if window has multiplier > 1 and SolarDistribution = FullExterior or FullInteriorExterior

  IF((SurfaceTmp(SurfNum)%Class == SurfaceClass_Window .or. SurfaceTmp(SurfNum)%Class == SurfaceClass_GlassDoor)  &
      .AND. SolarDistribution > MinimalShadowing .AND. SurfaceTmp(SurfNum)%Multiplier > 1.0d0) THEN
    IF (DisplayExtraWarnings) THEN
      CALL ShowWarningError(trim(cRoutineName)//': A Multiplier > 1.0 for window/glass door '//TRIM(SurfaceTmp(SurfNum)%Name))
      CALL ShowContinueError('in conjunction with SolarDistribution = FullExterior or FullInteriorExterior')
      CALL ShowContinueError('can cause inaccurate shadowing on the window and/or')
      CALL ShowContinueError('inaccurate interior solar distribution from the window.')
    ENDIF
    TotalMultipliedWindows=TotalMultipliedWindows+1
  END IF

  !  Require that a construction referenced by a surface that is a window
  !  NOT have a shading device layer; use WindowShadingControl to specify a shading device.
  ConstrNum=SurfaceTmp(SurfNum)%Construction
  IF(ConstrNum > 0) THEN
    NumShades = 0
    DO Lay = 1,Construct(ConstrNum)%TotLayers
      LayerPtr = Construct(ConstrNum)%LayerPoint(Lay)
      IF (LayerPtr == 0) CYCLE  ! Error is caught already, will terminate later
      IF(Material(LayerPtr)%Group==Shade .OR. Material(LayerPtr)%Group==WindowBlind .OR. &
         Material(LayerPtr)%Group==Screen) NumShades = NumShades + 1
    END DO
    IF(NumShades /= 0) THEN
      CALL ShowSevereError(trim(cRoutineName)//': Window "'//TRIM(SubSurfaceName)//'" must not directly reference')
      CALL ShowContinueError('a Construction (i.e, "'//TRIM(SubSurfaceConstruction)//'") with a shading device.')
      CALL ShowContinueError('Use WindowProperty:ShadingControl to specify a shading device for a window.')
      ErrorsFound = .true.
    END IF
  END IF

  ! Disallow glass transmittance dirt factor for interior windows and glass doors

  IF(SurfaceTmp(SurfNum)%ExtBoundCond /= ExternalEnvironment .AND. &
    (SurfaceTmp(SurfNum)%Class == SurfaceClass_Window .OR. SurfaceTmp(SurfNum)%Class == SurfaceClass_GlassDoor)) THEN
    ConstrNum = SurfaceTmp(SurfNum)%Construction
    IF (ConstrNum > 0) THEN
      DO Lay = 1,Construct(ConstrNum)%TotLayers
        LayerPtr = Construct(ConstrNum)%LayerPoint(Lay)
        IF(Material(LayerPtr)%Group == WindowGlass .AND. Material(LayerPtr)%GlassTransDirtFactor < 1.0d0) THEN
          CALL ShowSevereError(trim(cRoutineName)//': Interior Window or GlassDoor '//TRIM(SubSurfaceName)// &
            ' has a glass layer with')
          CALL ShowContinueError('Dirt Correction Factor for Solar and Visible Transmittance < 1.0')
          CALL ShowContinueError('A value less than 1.0 for this factor is only allowed for exterior windows and glass doors.')
          ErrorsFound = .true.
        END IF
      END DO
    ENDIF
  END IF

  ! If this is a window with a construction from the Window5DataFile, call routine that will
  ! (1) if one glazing system on Data File, give warning message if window height or width
  !     differ by more than 10% from those of the glazing system on the Data File;
  ! (2) if two glazing systems (separated by a mullion) on Data File, create a second window
  !     and adjust the dimensions of the original and second windows to those on the Data File

  IF (SurfaceTmp(SurfNum)%Construction /= 0) THEN

    IF(Construct(SurfaceTmp(SurfNum)%Construction)%FromWindow5DataFile) THEN

      CALL ModifyWindow(SurfNum,ErrorsFound,AddedSubSurfaces)

    ELSE
         ! Calculate net area for base surface (note that ModifyWindow, above, adjusts net area of
         ! base surface for case where window construction is from Window5 Data File
         ! In case there is in error in this window's base surface (i.e. none)..
      IF (SurfaceTmp(SurfNum)%BaseSurf > 0) THEN
        SurfaceTmp(SurfaceTmp(SurfNum)%BaseSurf)%Area =  &
               SurfaceTmp(SurfaceTmp(SurfNum)%BaseSurf)%Area - SurfaceTmp(SurfNum)%Area

        ! Subtract TDD:DIFFUSER area from other side interzone surface
        IF (SurfaceTmp(SurfNum)%Class == SurfaceClass_TDD_Diffuser .AND. &
          SurfaceTmp(SurfaceTmp(SurfNum)%BaseSurf)%ExtBoundCondName /= '   ') THEN ! Base surface is an interzone surface

          ! Lookup interzone surface of the base surface
          ! (Interzone surfaces have not been assigned yet, but all base surfaces should already be loaded.)
          Found = FindIteminList(SurfaceTmp(SurfaceTmp(SurfNum)%BaseSurf)%ExtBoundCondName,SurfaceTmp%Name,SurfNum)
          IF (Found /= 0) SurfaceTmp(Found)%Area = SurfaceTmp(Found)%Area - SurfaceTmp(SurfNum)%Area
        END IF

        IF (SurfaceTmp(SurfaceTmp(SurfNum)%BaseSurf)%Area <= 0.0d0) THEN
          CALL ShowSevereError(trim(cRoutineName)//': Surface Openings have too much area for base surface='//  &
                               TRIM(SurfaceTmp(SurfaceTmp(SurfNum)%BaseSurf)%Name))
          CALL ShowContinueError('Opening Surface creating error='//TRIM(SurfaceTmp(SurfNum)%Name))
          ErrorsFound=.true.
        ENDIF
           ! Net area of base surface with unity window multipliers (used in shadowing checks)
           ! For Windows, Glass Doors and Doors, just one area is subtracted.  For the rest, should be
           ! full area.
        IF (SurfaceTmp(SurfNum)%Class == SurfaceClass_Window .OR.SurfaceTmp(SurfNum)%Class == SurfaceClass_GlassDoor) THEN
          SurfaceTmp(SurfaceTmp(SurfNum)%BaseSurf)%NetAreaShadowCalc =  &
              SurfaceTmp(SurfaceTmp(SurfNum)%BaseSurf)%NetAreaShadowCalc -   &
                 SurfaceTmp(SurfNum)%Area/SurfaceTmp(SurfNum)%Multiplier
        ELSEIF (SurfaceTmp(SurfNum)%Class == SurfaceClass_Door) THEN ! Door, TDD:Diffuser, TDD:DOME
          SurfaceTmp(SurfaceTmp(SurfNum)%BaseSurf)%NetAreaShadowCalc =  &
            SurfaceTmp(SurfaceTmp(SurfNum)%BaseSurf)%NetAreaShadowCalc -   &
               SurfaceTmp(SurfNum)%Area/SurfaceTmp(SurfNum)%Multiplier
        ELSE
          SurfaceTmp(SurfaceTmp(SurfNum)%BaseSurf)%NetAreaShadowCalc =  &
             SurfaceTmp(SurfaceTmp(SurfNum)%BaseSurf)%NetAreaShadowCalc - SurfaceTmp(SurfNum)%Area
        ENDIF
      ENDIF
    ENDIF
  ENDIF

  RETURN

END SUBROUTINE CheckSubSurfaceMiscellaneous

SUBROUTINE MakeRelativeRectangularVertices(BaseSurfNum,SurfNum,XCoord,ZCoord,Length,Height)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Linda Lawrie
          !       DATE WRITTEN   December 2008
          !       MODIFIED       na
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! This routine creates world/3d coordinates for rectangular surfaces using relative X and Z, length & height.

          ! METHODOLOGY EMPLOYED:
          ! na

          ! REFERENCES:
          ! na

          ! USE STATEMENTS:
  USE Vectors

  IMPLICIT NONE ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
  INTEGER, INTENT(IN) :: BaseSurfNum  ! Base surface
  INTEGER, INTENT(IN) :: SurfNum
  REAL(r64), INTENT(IN) :: XCoord
  REAL(r64), INTENT(IN) :: ZCoord
  REAL(r64), INTENT(IN) :: Length
  REAL(r64), INTENT(IN) :: Height

          ! SUBROUTINE PARAMETER DEFINITIONS:
          ! na

          ! INTERFACE BLOCK SPECIFICATIONS:
          ! na

          ! DERIVED TYPE DEFINITIONS:
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
  REAL(r64) :: SurfAzimuth  ! Surface Azimuth/Facing (same as Base Surface)
  REAL(r64) :: SurfTilt     ! Tilt (same as Base Surface)
  REAL(r64) :: XLLC
  REAL(r64) :: YLLC
  REAL(r64) :: ZLLC
  REAL(r64) :: CosSurfAzimuth
  REAL(r64) :: SinSurfAzimuth
  REAL(r64) :: CosSurfTilt
  REAL(r64) :: SinSurfTilt
  REAL(r64) :: BaseCosSurfAzimuth
  REAL(r64) :: BaseSinSurfAzimuth
  REAL(r64) :: BaseCosSurfTilt
  REAL(r64) :: BaseSinSurfTilt
  REAL(r64) :: XX(4),YY(4)
  REAL(r64) :: Perimeter
  INTEGER :: N
  INTEGER :: Vrt


  IF (BaseSurfNum == 0) RETURN  ! invalid base surface, don't bother

  ! Tilt and Facing (Azimuth) will be same as the Base Surface

  SurfaceTmp(SurfNum)%Height=Height
  SurfaceTmp(SurfNum)%Width=Length

  SurfAzimuth = SurfaceTmp(SurfNum)%Azimuth
  SurfTilt    = SurfaceTmp(SurfNum)%Tilt
  CosSurfAzimuth=COS(SurfAzimuth*DegToRadians)
  SinSurfAzimuth=SIN(SurfAzimuth*DegToRadians)
  CosSurfTilt=COS(SurfTilt*DegToRadians)
  SinSurfTilt=SIN(SurfTilt*DegToRadians)
  BaseCosSurfAzimuth=SurfaceTmp(BaseSurfNum)%CosAzim
  BaseSinSurfAzimuth=SurfaceTmp(BaseSurfNum)%SinAzim
  BaseCosSurfTilt=SurfaceTmp(BaseSurfNum)%CosTilt
  BaseSinSurfTilt=SurfaceTmp(BaseSurfNum)%SinTilt

  XLLC  = SurfaceTmp(BaseSurfNum)%Vertex(2)%X-XCoord*BaseCosSurfAzimuth-ZCoord*BaseCosSurfTilt*BaseSinSurfAzimuth
  YLLC  = SurfaceTmp(BaseSurfNum)%Vertex(2)%Y+XCoord*BaseSinSurfAzimuth-ZCoord*BaseCosSurfTilt*BaseCosSurfAzimuth
  ZLLC  = SurfaceTmp(BaseSurfNum)%Vertex(2)%Z+ZCoord*BaseSinSurfTilt

  XX(1)=0.0d0
  XX(2)=0.0d0
  XX(3)=Length
  XX(4)=Length
  YY(1)=Height
  YY(4)=Height
  YY(3)=0.0d0
  YY(2)=0.0d0

  DO N = 1, SurfaceTmp(SurfNum)%Sides
    Vrt=N
    SurfaceTmp(SurfNum)%Vertex(Vrt)%X=XLLC-XX(N)*CosSurfAzimuth-YY(N)*CosSurfTilt*SinSurfAzimuth
    SurfaceTmp(SurfNum)%Vertex(Vrt)%Y=YLLC+XX(N)*SinSurfAzimuth-YY(N)*CosSurfTilt*CosSurfAzimuth
    SurfaceTmp(SurfNum)%Vertex(Vrt)%Z=ZLLC+YY(N)*SinSurfTilt
  END DO

  CALL CreateNewellAreaVector(SurfaceTmp(SurfNum)%Vertex,SurfaceTmp(SurfNum)%Sides,SurfaceTmp(SurfNum)%NewellAreaVector)
  SurfaceTmp(SurfNum)%GrossArea=VecLength(SurfaceTmp(SurfNum)%NewellAreaVector)
  SurfaceTmp(SurfNum)%Area=SurfaceTmp(SurfNum)%GrossArea
  SurfaceTmp(SurfNum)%NetAreaShadowCalc = SurfaceTmp(SurfNum)%Area
  CALL CreateNewellSurfaceNormalVector(SurfaceTmp(SurfNum)%Vertex,SurfaceTmp(SurfNum)%Sides,  &
     SurfaceTmp(SurfNum)%NewellSurfaceNormalVector)
  CALL DetermineAzimuthAndTilt(SurfaceTmp(SurfNum)%Vertex,SurfaceTmp(SurfNum)%Sides,SurfAzimuth,SurfTilt,  &
                               SurfaceTmp(SurfNum)%lcsx,SurfaceTmp(SurfNum)%lcsy,SurfaceTmp(SurfNum)%lcsz, &
                               SurfaceTmp(SurfNum)%GrossArea,SurfaceTmp(SurfNum)%NewellSurfaceNormalVector)
  SurfaceTmp(SurfNum)%Azimuth=SurfAzimuth
  SurfaceTmp(SurfNum)%Tilt=SurfTilt
  ! Sine and cosine of azimuth and tilt
  SurfaceTmp(SurfNum)%SinAzim = SinSurfAzimuth
  SurfaceTmp(SurfNum)%CosAzim = CosSurfAzimuth
  SurfaceTmp(SurfNum)%SinTilt = SinSurfTilt
  SurfaceTmp(SurfNum)%CosTilt = CosSurfTilt
  IF (SurfaceTmp(SurfNum)%Class /= SurfaceClass_Window .and. SurfaceTmp(SurfNum)%Class /= SurfaceClass_GlassDoor .and.  &
      SurfaceTmp(SurfNum)%Class /= SurfaceClass_Door) &
    SurfaceTmp(SurfNum)%ViewFactorGround = 0.5d0 * (1.0d0 - SurfaceTmp(SurfNum)%CosTilt)
  ! 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_Roof .and. SurfTilt > 80.) THEN
!    WRITE(TiltString,'(F5.1)') SurfTilt
!    TiltString=ADJUSTL(TiltString)
!    CALL ShowWarningError('Roof/Ceiling Tilt='//TRIM(TiltString)//', much greater than expected tilt of 0,'// &
!                          ' for Surface='//TRIM(SurfaceTmp(SurfNum)%Name)//  &
!                          ', in Zone='//TRIM(SurfaceTmp(SurfNum)%ZoneName))
!  ENDIF
!  IF (SurfaceTmp(SurfNum)%Class == SurfaceClass_Floor .and. SurfTilt < 170.) THEN
!    WRITE(TiltString,'(F5.1)') SurfTilt
!    TiltString=ADJUSTL(TiltString)
!    CALL ShowWarningError('Floor Tilt='//TRIM(TiltString)//', much less than expected tilt of 180,'//   &
!                          ' for Surface='//TRIM(SurfaceTmp(SurfNum)%Name)//  &
!                          ', in Zone='//TRIM(SurfaceTmp(SurfNum)%ZoneName))
!  ENDIF
  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)

  Perimeter=Distance(SurfaceTmp(SurfNum)%Vertex(SurfaceTmp(SurfNum)%Sides),SurfaceTmp(SurfNum)%Vertex(1))
  DO Vrt=2,SurfaceTmp(SurfNum)%Sides
    Perimeter = Perimeter+Distance(SurfaceTmp(SurfNum)%Vertex(Vrt),SurfaceTmp(SurfNum)%Vertex(Vrt-1))
  ENDDO
  SurfaceTmp(SurfNum)%Perimeter=Perimeter

  ! Call to transform vertices

  Call TransformVertsByAspect(SurfNum,SurfaceTmp(SurfNum)%Sides)

  RETURN

END SUBROUTINE MakeRelativeRectangularVertices

SUBROUTINE GetAttShdSurfaceData(ErrorsFound,SurfNum,TotShdSubs)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Linda Lawrie
          !       DATE WRITTEN   May 2000
          !       MODIFIED       na
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! This subroutine gets the HeatTransfer Surface Data,
          ! checks it for errors, etc.

          ! METHODOLOGY EMPLOYED:
          ! na

          ! REFERENCES:
  !  Attached Shading Surface Definition
  !Surface:Shading:Attached,
  !       \memo used For fins, overhangs, elements that shade the building, are attached to the building
  !       \memo but are not part of the heat transfer calculations
  !  A1 , \field User Supplied Surface Name
  !       \required-field
  !       \type alpha
  !       \reference AttachedShadingSurfNames
  !  A2 , \field Base Surface Name
  !       \required-field
  !       \type object-list
  !       \object-list SurfaceNames
  !  A3,  \field TransSchedShadowSurf
  !       \note Transmittance schedule for the shading device, defaults to zero (always opaque)
  !       \type object-list
  !       \object-list ScheduleNames
  !  N1 , \field Number of Surface Vertex Groups -- Number of (X,Y,Z) groups in this surface
  !       \required-field
  !       \note currently limited 3 or 4, later?
  !       \minimum 3
  !       \maximum 4
  !       \note vertices are given in SurfaceGeometry coordinates -- if relative, all surface coordinates
  !       \note are "relative" to the Zone Origin.  if WCS, then building and zone origins are used
  !       \note for some internal calculations, but all coordinates are given in an "absolute" system.
  !  N2,  \field Vertex 1 X-coordinate
  !       \units m
  !       \type real
  !  N3-13; as indicated by the N2 value

          ! USE STATEMENTS:
  USE DataIPShortCuts
  USE InputProcessor, ONLY: GetNumObjectsFound, GetObjectItem, FindItemInList, VerifyName, GetObjectDefMaxArgs
  USE ScheduleManager, ONLY: GetScheduleIndex,CheckScheduleValueMinMax,GetScheduleMinValue,GetScheduleMaxValue
  USE General, ONLY: TrimSigDigits
  USE DataReportingFlags

  IMPLICIT NONE    ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
  LOGICAL, INTENT(INOUT)      :: ErrorsFound       ! Error flag indicator (true if errors found)
  INTEGER, INTENT(INOUT)      :: SurfNum           ! Count of Current SurfaceNumber
  INTEGER, INTENT(IN)         :: TotShdSubs        ! Number of Attached Shading SubSurfaces to obtain

          ! SUBROUTINE PARAMETER DEFINITIONS:
          ! na

          ! INTERFACE BLOCK SPECIFICATIONS
          ! na

          ! DERIVED TYPE DEFINITIONS
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
  INTEGER :: IOStat            ! IO Status when calling get input subroutine
  INTEGER :: NumAlphas         ! Number of alpha names being passed
  INTEGER :: NumNumbers        ! Number of properties being passed
  INTEGER :: Found             ! For matching interzone surfaces
  INTEGER :: Loop
  LOGICAL :: ErrorInName
  LOGICAL :: IsBlank
  REAL(r64) :: SchedMinValue
  REAL(r64) :: SchedMaxValue

  IF (TotShdSubs > 0 .and. SolarDistribution == MinimalShadowing) THEN
    CALL ShowWarningError('Shading effects of Fins and Overhangs are ignored when Solar Distribution = MinimalShadowing')
  ENDIF

  cCurrentModuleObject='Shading:Zone:Detailed'
  CALL GetObjectDefMaxArgs(cCurrentModuleObject,Loop,NumAlphas,NumNumbers)
  IF (NumAlphas /= 3) THEN
    CALL ShowSevereError(TRIM(cCurrentModuleObject)//': Object Definition indicates '// &
                         'not = 3 Alpha Objects, Number Indicated='//  &
                         TRIM(TrimSigDigits(NumAlphas)))
    ErrorsFound=.true.
  ENDIF

  DO Loop=1,TotShdSubs
    CALL GetObjectItem(cCurrentModuleObject,Loop,cAlphaArgs,NumAlphas, &
                       rNumericArgs,NumNumbers,IOSTAT,  &
                   AlphaBlank=lAlphaFieldBlanks,NumBlank=lNumericFieldBlanks,  &
                   AlphaFieldnames=cAlphaFieldNames,NumericFieldNames=cNumericFieldNames)
    ErrorInName=.false.
    IsBlank=.false.
    CALL VerifyName(cAlphaArgs(1),SurfaceTmp%Name,SurfNum,ErrorInName,IsBlank,TRIM(cCurrentModuleObject)//' Name')
    IF (ErrorInName) THEN
      CALL ShowContinueError('...each surface name must not duplicate other surface names (of any type)')
      ErrorsFound=.true.
      CYCLE
    ENDIF

    SurfNum=SurfNum+1
    SurfaceTmp(SurfNum)%Name = cAlphaArgs(1)  ! Set the Surface Name in the Derived Type
    SurfaceTmp(SurfNum)%Class= SurfaceClass_Shading
    SurfaceTmp(SurfNum)%HeatTransSurf=.false.
    SurfaceTmp(SurfNum)%BaseSurfName=cAlphaArgs(2)
    !  The subsurface inherits properties from the base surface
    !  Exterior conditions, Zone, etc.
    !  We can figure out the base surface though, because they've all been entered
    Found=FindIteminList(SurfaceTmp(SurfNum)%BaseSurfName,SurfaceTmp%Name,TotSurfaces)
    IF (Found > 0) THEN
      !SurfaceTmp(SurfNum)%BaseSurf=Found
      SurfaceTmp(SurfNum)%ExtBoundCond=SurfaceTmp(Found)%ExtBoundCond
      SurfaceTmp(SurfNum)%ExtSolar=SurfaceTmp(Found)%ExtSolar
      SurfaceTmp(SurfNum)%ExtWind=SurfaceTmp(Found)%ExtWind
      SurfaceTmp(SurfNum)%Zone=SurfaceTmp(Found)%Zone ! Necessary to do relative coordinates in GetVertices below
      SurfaceTmp(SurfNum)%ZoneName=SurfaceTmp(Found)%ZoneName ! Necessary to have surface drawn in OutputReports
    ELSE
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                             '", invalid '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2)))
      ErrorsFound=.true.
    ENDIF
    IF (SurfaceTmp(SurfNum)%ExtBoundCond == UnenteredAdjacentZoneSurface) THEN
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                             '", invalid '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2)))
      CALL ShowContinueError('...trying to attach a shading device to an interzone surface.')
      ErrorsFound=.true.
      SurfaceTmp(SurfNum)%ExtBoundCond = ExternalEnvironment  ! reset so program won't crash during "add surfaces"
    ENDIF
    IF (SurfaceTmp(SurfNum)%ExtBoundCond == UnreconciledZoneSurface) THEN
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                             '", invalid '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2)))
      CALL ShowContinueError('...trying to attach a shading device to an interior surface.')
      ErrorsFound=.true.
      SurfaceTmp(SurfNum)%ExtBoundCond = ExternalEnvironment  ! reset so program won't crash during "add surfaces"
    ENDIF

    IF (.not. lAlphaFieldBlanks(3)) THEN
      SurfaceTmp(SurfNum)%SchedShadowSurfIndex = GetScheduleIndex(cAlphaArgs(3))
      IF (SurfaceTmp(SurfNum)%SchedShadowSurfIndex == 0) THEN
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                             '", '//TRIM(cAlphaFieldNames(3))//' not found="'//TRIM(cAlphaArgs(3)))
        ErrorsFound=.true.
      ENDIF
    ELSE
      SurfaceTmp(SurfNum)%SchedShadowSurfIndex=0
    ENDIF
    IF (SurfaceTmp(SurfNum)%SchedShadowSurfIndex /= 0) THEN
      IF (.not. CheckScheduleValueMinMax(SurfaceTmp(SurfNum)%SchedShadowSurfIndex,'>=',0.0d0,'<=',1.0d0)) THEN
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                             '", '//TRIM(cAlphaFieldNames(3))//'="'//TRIM(cAlphaArgs(3))// &
                             '", values not in range [0,1].')
        ErrorsFound=.true.
      ENDIF
      SchedMinValue=GetScheduleMinValue(SurfaceTmp(SurfNum)%SchedShadowSurfIndex)
      SurfaceTmp(SurfNum)%SchedMinValue=SchedMinValue
      SchedMaxValue=GetScheduleMaxValue(SurfaceTmp(SurfNum)%SchedShadowSurfIndex)
      IF (SchedMinValue == 1.0d0) THEN
        CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                             '", '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))// &
                             '", is always transparent.')
        SurfaceTmp(SurfNum)%IsTransparent=.true.
      ENDIF
      IF (SchedMinValue < 0.0d0) THEN
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                             '", '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))// &
                             '", has schedule values < 0.')
        CALL ShowContinueError('...Schedule values < 0 have no meaning for shading elements.')
      ENDIF
      IF (SchedMaxValue > 1.0d0) THEN
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                             '", '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))// &
                             '", has schedule values > 1.')
        CALL ShowContinueError('...Schedule values > 1 have no meaning for shading elements.')
      ENDIF
      IF (ABS(SchedMinValue-SchedMaxValue) > 1.0d-6) THEN
        SurfaceTmp(SurfNum)%ShadowSurfSchedVaries=.true.
        ShadingTransmittanceVaries=.true.
      ENDIF
    ENDIF
    IF (lNumericFieldBlanks(1) .or. rNumericArgs(1) == AutoCalculate) THEN
      rNumericArgs(1)=(NumNumbers-1)/3
      SurfaceTmp(SurfNum)%Sides=rNumericArgs(1)
      IF (MOD(NumNumbers-1,3) /= 0) THEN
        CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                             '", '//TRIM(cNumericFieldNames(1))//          &
                              ' not even multiple of 3. Will read in '//   &
                              TRIM(TrimSigDigits(SurfaceTmp(SurfNum)%Sides)))
      ENDIF
      IF (rNumericArgs(1) < 3) THEN
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                             '", '//TRIM(cNumericFieldNames(1))//' (autocalculate) must be >= 3. Only '//  &
                             TRIM(TrimSigDigits(SurfaceTmp(SurfNum)%Sides))//' provided.')
        ErrorsFound=.true.
        CYCLE
      ENDIF
    ELSE
      SurfaceTmp(SurfNum)%Sides=rNumericArgs(1)
    ENDIF
    ALLOCATE(SurfaceTmp(SurfNum)%Vertex(SurfaceTmp(SurfNum)%Sides))
    CALL GetVertices(SurfNum,SurfaceTmp(SurfNum)%Sides,rNumericArgs(2:))
    CALL CheckConvexity(SurfNum,SurfaceTmp(SurfNum)%Sides)
!    IF (SurfaceTmp(SurfNum)%Sides == 3) THEN
!      CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
!                        ' should not be triangular.')
!      CALL ShowContinueError('...Check results carefully.')
!      ErrorsFound=.true.
!    ENDIF
    ! Reset surface to be "detached"
    SurfaceTmp(SurfNum)%BaseSurf=0
!    SurfaceTmp(SurfNum)%BaseSurfName='  '
    SurfaceTmp(SurfNum)%Zone=0
    !SurfaceTmp(SurfNum)%ZoneName='  '
    IF (MakeMirroredAttachedShading) THEN
      CALL MakeMirrorSurface(SurfNum)
    END IF

  ENDDO

  RETURN

END SUBROUTINE GetAttShdSurfaceData

SUBROUTINE GetSimpleShdSurfaceData(ErrorsFound,SurfNum,TotOverhangs,TotOverhangsProjection,TotFins,TotFinsProjection)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Linda Lawrie
          !       DATE WRITTEN   January 2009
          !       MODIFIED       na
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! Get simple overhang and fin descriptions.

          ! METHODOLOGY EMPLOYED:
          ! na

          ! REFERENCES:
          ! na

          ! USE STATEMENTS:
  USE DataIPShortCuts
  USE InputProcessor, ONLY: GetNumObjectsFound, GetObjectItem, FindItemInList, VerifyName, GetObjectDefMaxArgs
  USE General, ONLY: TrimSigDigits,RoundSigDigits
  USE DataReportingFlags
  USE Vectors

  IMPLICIT NONE ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
  LOGICAL, INTENT(INOUT)         :: ErrorsFound       ! Error flag indicator (true if errors found)
  INTEGER, INTENT(INOUT)         :: SurfNum           ! Count of Current SurfaceNumber
  INTEGER, INTENT(IN)            :: TotOverhangs      ! Number of Overhangs to obtain
  INTEGER, INTENT(IN)            :: TotOverhangsProjection  ! Number of Overhangs (projection) to obtain
  INTEGER, INTENT(IN)            :: TotFins           ! Number of Fins to obtain
  INTEGER, INTENT(IN)            :: TotFinsProjection ! Number of Fins (projection) to obtain

          ! SUBROUTINE PARAMETER DEFINITIONS:
  CHARACTER(len=*), PARAMETER, DIMENSION(4) :: cModuleObjects=  &
    (/'Shading:Overhang           ',  &
      'Shading:Overhang:Projection',  &
      'Shading:Fin                ',  &
      'Shading:Fin:Projection     '/)
  CHARACTER(len=*), PARAMETER :: dfmt='(A,3(2x,f6.2))'

          ! INTERFACE BLOCK SPECIFICATIONS:
          ! na

          ! DERIVED TYPE DEFINITIONS:
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
  INTEGER :: Item
  INTEGER :: ItemsToGet
  INTEGER :: Loop
  INTEGER :: NumAlphas
  INTEGER :: NumNumbers
  INTEGER :: IOStat            ! IO Status when calling get input subroutine
  INTEGER :: Found             ! For matching base surfaces
  LOGICAL :: ErrorInName
  LOGICAL :: IsBlank
  REAL(r64) :: Depth
  REAL(r64) :: Length
  REAL(r64) :: Xp
  REAL(r64) :: Yp
  REAL(r64) :: Zp
  REAL(r64) :: XLLC
  REAL(r64) :: YLLC
  INTEGER :: BaseSurfNum
  REAL(r64) :: TiltAngle
  LOGICAL :: MakeFin

  IF ((TotOverhangs+TotOverhangsProjection+TotFins+TotFinsProjection) > 0 .and. SolarDistribution == MinimalShadowing) THEN
    CALL ShowWarningError('Shading effects of Fins and Overhangs are ignored when Solar Distribution = MinimalShadowing')
  ENDIF

  DO Item=1,4

    cCurrentModuleObject=cModuleObjects(Item)
    IF (Item == 1) THEN
      ItemsToGet=TotOverhangs
    ELSEIF (Item == 2) THEN
      ItemsToGet=TotOverhangsProjection
    ELSEIF (Item == 3) THEN
      ItemsToGet=TotFins
    ELSE  ! ! (Item == 4) THEN
      ItemsToGet=TotFinsProjection
    ENDIF

    DO Loop=1,ItemsToGet
      CALL GetObjectItem(cCurrentModuleObject,Loop,cAlphaArgs,NumAlphas,rNumericArgs,NumNumbers,IOSTAT,  &
                     AlphaBlank=lAlphaFieldBlanks,NumBlank=lNumericFieldBlanks,  &
                     AlphaFieldnames=cAlphaFieldNames,NumericFieldNames=cNumericFieldNames)
      ErrorInName=.false.
      IsBlank=.false.
      CALL VerifyName(cAlphaArgs(1),SurfaceTmp%Name,SurfNum,ErrorInName,IsBlank,TRIM(cCurrentModuleObject)//' Name')
      IF (ErrorInName) THEN
        CALL ShowContinueError('...each surface name must not duplicate other surface names (of any type)')
        ErrorsFound=.true.
        CYCLE
      ENDIF

      SurfNum=SurfNum+1
      SurfaceTmp(SurfNum)%Name = cAlphaArgs(1)  ! Set the Surface Name in the Derived Type
      SurfaceTmp(SurfNum)%Class= SurfaceClass_Shading
      SurfaceTmp(SurfNum)%HeatTransSurf=.false.
      ! this object references a window or door....
      Found=FindIteminList(cAlphaArgs(2),SurfaceTmp%Name,TotSurfaces)
      IF (Found > 0) THEN
        BaseSurfNum=SurfaceTmp(Found)%BaseSurf
        SurfaceTmp(SurfNum)%BaseSurfName=SurfaceTmp(Found)%BaseSurfName
        SurfaceTmp(SurfNum)%ExtBoundCond=SurfaceTmp(Found)%ExtBoundCond
        SurfaceTmp(SurfNum)%ExtSolar=SurfaceTmp(Found)%ExtSolar
        SurfaceTmp(SurfNum)%ExtWind=SurfaceTmp(Found)%ExtWind
        SurfaceTmp(SurfNum)%Zone=SurfaceTmp(Found)%Zone ! Necessary to do relative coordinates in GetVertices below
        SurfaceTmp(SurfNum)%ZoneName=SurfaceTmp(Found)%ZoneName ! Necessary to have surface drawn in OutputReports
      ELSE
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                               '", invalid '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2)))
        ErrorsFound=.true.
        CYCLE
      ENDIF
      IF (SurfaceTmp(SurfNum)%ExtBoundCond == UnenteredAdjacentZoneSurface) THEN
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                               '", invalid '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2)))
        CALL ShowContinueError('...trying to attach a shading device to an interzone surface.')
        ErrorsFound=.true.
        SurfaceTmp(SurfNum)%ExtBoundCond = ExternalEnvironment  ! reset so program won't crash during "add surfaces"
      ENDIF
      IF (SurfaceTmp(SurfNum)%ExtBoundCond == UnreconciledZoneSurface) THEN
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                               '", invalid '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2)))
        CALL ShowContinueError('...trying to attach a shading device to an interior surface.')
        ErrorsFound=.true.
        SurfaceTmp(SurfNum)%ExtBoundCond = ExternalEnvironment  ! reset so program won't crash during "add surfaces"
      ENDIF

      SurfaceTmp(SurfNum)%SchedShadowSurfIndex=0

!===== Overhang =====

      IF (Item < 3) THEN
        !  Found is the surface window or door.
        !   N1,  \field Height above Window or Door
        !        \units m
        !   N2,  \field Tilt Angle from Window/Door
        !        \units deg
        !        \default 90
        !        \minimum 0
        !        \maximum 180
        !   N3,  \field Left extension from Window/Door Width
        !        \units m
        !   N4,  \field Right extension from Window/Door Width
        !        \note N3 + N4 + Window/Door Width is Overhang Length
        !        \units m
        !   N5;  \field Depth
        !        \units m
        ! for projection option:
        !   N5;  \field Depth as Fraction of Window/Door Height
        !        \units m
        Length=rNumericArgs(3)+rNumericArgs(4)+SurfaceTmp(Found)%Width
        IF (Item == 1) THEN
          Depth=rNumericArgs(5)
        ELSEIF (Item == 2) THEN
          Depth=rNumericArgs(5)*SurfaceTmp(Found)%Height
        ENDIF

        IF (Length*Depth <= 0.0d0) THEN
          CALL ShowSevereError(trim(cCurrentModuleObject)//'="'//trim(cAlphaArgs(1))//'", illegal surface area=['//  &
            trim(RoundSigDigits(Length*Depth,2))//']. Surface will NOT be entered.')
          CYCLE
        ENDIF

        TiltAngle=SurfaceTmp(Found)%Tilt+rNumericArgs(2)
        SurfaceTmp(SurfNum)%Tilt=TiltAngle
        SurfaceTmp(SurfNum)%Azimuth=SurfaceTmp(Found)%Azimuth

        ! Make it relative to surface origin.....
        Xp=SurfaceTmp(Found)%Vertex(2)%x-SurfaceTmp(BaseSurfNum)%Vertex(2)%x
        Yp=SurfaceTmp(Found)%Vertex(2)%y-SurfaceTmp(BaseSurfNum)%Vertex(2)%y
        Zp=SurfaceTmp(Found)%Vertex(2)%z-SurfaceTmp(BaseSurfNum)%Vertex(2)%z

        XLLC=-Xp*SurfaceTmp(BaseSurfNum)%CosAzim+Yp*SurfaceTmp(BaseSurfNum)%SinAzim

        YLLC=-Xp*SurfaceTmp(BaseSurfNum)%SinAzim*SurfaceTmp(BaseSurfNum)%CosTilt-  &
           Yp*SurfaceTmp(BaseSurfNum)%CosAzim*SurfaceTmp(BaseSurfNum)%CosTilt+Zp*SurfaceTmp(BaseSurfNum)%SinTilt

        SurfaceTmp(SurfNum)%Sides=4
        ALLOCATE(SurfaceTmp(SurfNum)%Vertex(SurfaceTmp(SurfNum)%Sides))

        CALL MakeRelativeRectangularVertices(BaseSurfNum,SurfNum,  &
                         XLLC-rNumericArgs(3),YLLC+SurfaceTmp(Found)%Height+rNumericArgs(1),Length,Depth)


      ! Reset surface to be "detached"
      !    SurfaceTmp(SurfNum)%BaseSurfName='  '
      !    SurfaceTmp(SurfNum)%ZoneName='  '

        SurfaceTmp(SurfNum)%BaseSurf=0
        SurfaceTmp(SurfNum)%Zone=0

      ! and mirror
        IF (MakeMirroredAttachedShading) THEN
          CALL MakeMirrorSurface(SurfNum)
        END IF

      ELSE  ! Fins

!===== Fins =====

!===== Left Fin =====

        !   N1,  \field Left Extension from Window/Door
        !        \units m
        !   N2,  \field Left Distance Above Top of Window
        !        \units m
        !   N3,  \field Left Distance Below Bottom of Window
        !        \units m
        !        \note N2 + N3 + height of Window/Door is height of Fin
        !   N4,  \field Left Tilt Angle from Window/Door
        !        \units deg
        !        \default 90
        !        \minimum 0
        !        \maximum 180
        !   N5,  \field Left Depth
        !        \units m
        ! for projection option:
        !   N5,  \field Left Depth as Fraction of Window/Door Width
        !        \units m
        SurfaceTmp(SurfNum)%Name=TRIM(SurfaceTmp(SurfNum)%Name)//' Left'
        Length=rNumericArgs(2)+rNumericArgs(3)+SurfaceTmp(Found)%Height
        IF (Item == 3) THEN
          Depth=rNumericArgs(5)
        ELSEIF (Item == 4) THEN
          Depth=rNumericArgs(5)*SurfaceTmp(Found)%Width
        ENDIF

        MakeFin=.true.
        IF (Length*Depth <= 0.0d0) THEN
          CALL ShowWarningError(trim(cCurrentModuleObject)//'=Left Fin of "'//trim(cAlphaArgs(1))//  &
            '", illegal surface area=['//  &
            trim(RoundSigDigits(Length*Depth,2))//']. Surface will NOT be entered.')
          MakeFin=.false.
        ENDIF

        IF (MakeFin) THEN
          TiltAngle=SurfaceTmp(Found)%Tilt
          SurfaceTmp(SurfNum)%Tilt=TiltAngle
          SurfaceTmp(SurfNum)%Azimuth=SurfaceTmp(Found)%Azimuth-(180.0d0-rNumericArgs(4))

          ! Make it relative to surface origin.....

          Xp=SurfaceTmp(Found)%Vertex(2)%x-SurfaceTmp(BaseSurfNum)%Vertex(2)%x
          Yp=SurfaceTmp(Found)%Vertex(2)%y-SurfaceTmp(BaseSurfNum)%Vertex(2)%y
          Zp=SurfaceTmp(Found)%Vertex(2)%z-SurfaceTmp(BaseSurfNum)%Vertex(2)%z

          XLLC=-Xp*SurfaceTmp(BaseSurfNum)%CosAzim+Yp*SurfaceTmp(BaseSurfNum)%SinAzim

          YLLC=-Xp*SurfaceTmp(BaseSurfNum)%SinAzim*SurfaceTmp(BaseSurfNum)%CosTilt-  &
             Yp*SurfaceTmp(BaseSurfNum)%CosAzim*SurfaceTmp(BaseSurfNum)%CosTilt+Zp*SurfaceTmp(BaseSurfNum)%SinTilt

          SurfaceTmp(SurfNum)%CosAzim=COS(SurfaceTmp(SurfNum)%Azimuth*DegToRadians)
          SurfaceTmp(SurfNum)%SinAzim=SIN(SurfaceTmp(SurfNum)%Azimuth*DegToRadians)
          SurfaceTmp(SurfNum)%CosTilt=COS(SurfaceTmp(SurfNum)%Tilt*DegToRadians)
          SurfaceTmp(SurfNum)%SinTilt=SIN(SurfaceTmp(SurfNum)%Tilt*DegToRadians)

          SurfaceTmp(SurfNum)%Sides=4
          ALLOCATE(SurfaceTmp(SurfNum)%Vertex(SurfaceTmp(SurfNum)%Sides))

          CALL MakeRelativeRectangularVertices(BaseSurfNum,SurfNum,  &
                           XLLC-rNumericArgs(1),YLLC-rNumericArgs(3),-Depth,Length)

        ! Reset surface to be "detached"
        !    SurfaceTmp(SurfNum)%BaseSurfName='  '
        !    SurfaceTmp(SurfNum)%ZoneName='  '

          SurfaceTmp(SurfNum)%BaseSurf=0
          SurfaceTmp(SurfNum)%Zone=0

        ! and mirror
          IF (MakeMirroredAttachedShading) THEN
            CALL MakeMirrorSurface(SurfNum)
          END IF
        ELSE
          SurfNum=SurfNum-1
        ENDIF

!===== Right Fin =====

        !   N6,  \field Right Extension from Window/Door
        !        \units m
        !   N7,  \field Right Distance Above Top of Window
        !        \units m
        !   N8,  \field Right Distance Below Bottom of Window
        !        \note N7 + N8 + height of Window/Door is height of Fin
        !        \units m
        !   N9,  \field Right Tilt Angle from Window/Door
        !        \units deg
        !        \default 90
        !        \minimum 0
        !        \maximum 180
        !   N10; \field Right Depth
        !        \units m
        ! for projection option:
        !   N10; \field Right Depth as Fraction of Window/Door Width
        !        \units m

        SurfNum=SurfNum+1
        SurfaceTmp(SurfNum)%Name = TRIM(cAlphaArgs(1))//' Right'  ! Set the Surface Name in the Derived Type
        SurfaceTmp(SurfNum)%Class= SurfaceClass_Shading
        SurfaceTmp(SurfNum)%HeatTransSurf=.false.
        BaseSurfNum=SurfaceTmp(Found)%BaseSurf
        SurfaceTmp(SurfNum)%BaseSurfName=SurfaceTmp(Found)%BaseSurfName
        SurfaceTmp(SurfNum)%ExtBoundCond=SurfaceTmp(Found)%ExtBoundCond
        SurfaceTmp(SurfNum)%ExtSolar=SurfaceTmp(Found)%ExtSolar
        SurfaceTmp(SurfNum)%ExtWind=SurfaceTmp(Found)%ExtWind
        SurfaceTmp(SurfNum)%Zone=SurfaceTmp(Found)%Zone ! Necessary to do relative coordinates in GetVertices below
        SurfaceTmp(SurfNum)%ZoneName=SurfaceTmp(Found)%ZoneName ! Necessary to have surface drawn in OutputReports

        SurfaceTmp(SurfNum)%SchedShadowSurfIndex=0
        Length=rNumericArgs(7)+rNumericArgs(8)+SurfaceTmp(Found)%Height
        IF (Item == 3) THEN
          Depth=rNumericArgs(10)
        ELSEIF (Item == 4) THEN
          Depth=rNumericArgs(10)*SurfaceTmp(Found)%Width
        ENDIF

        MakeFin=.true.
        IF (Length*Depth <= 0.0d0) THEN
          CALL ShowWarningError(trim(cCurrentModuleObject)//'=Right Fin of "'//trim(cAlphaArgs(1))//  &
            '", illegal surface area=['//  &
            trim(RoundSigDigits(Length*Depth,2))//']. Surface will NOT be entered.')
          MakeFin=.false.
        ENDIF

        IF (MakeFin) THEN
          ! Make it relative to surface origin.....

          Xp=SurfaceTmp(Found)%Vertex(2)%x-SurfaceTmp(BaseSurfNum)%Vertex(2)%x
          Yp=SurfaceTmp(Found)%Vertex(2)%y-SurfaceTmp(BaseSurfNum)%Vertex(2)%y
          Zp=SurfaceTmp(Found)%Vertex(2)%z-SurfaceTmp(BaseSurfNum)%Vertex(2)%z

          XLLC=-Xp*SurfaceTmp(BaseSurfNum)%CosAzim+Yp*SurfaceTmp(BaseSurfNum)%SinAzim

          YLLC=-Xp*SurfaceTmp(BaseSurfNum)%SinAzim*SurfaceTmp(BaseSurfNum)%CosTilt-  &
              Yp*SurfaceTmp(BaseSurfNum)%CosAzim*SurfaceTmp(BaseSurfNum)%CosTilt+Zp*SurfaceTmp(BaseSurfNum)%SinTilt

          TiltAngle=SurfaceTmp(Found)%Tilt
          SurfaceTmp(SurfNum)%Tilt=TiltAngle
          SurfaceTmp(SurfNum)%Azimuth=SurfaceTmp(Found)%Azimuth-(180.0-rNumericArgs(9))
          SurfaceTmp(SurfNum)%CosAzim=COS(SurfaceTmp(SurfNum)%Azimuth*DegToRadians)
          SurfaceTmp(SurfNum)%SinAzim=SIN(SurfaceTmp(SurfNum)%Azimuth*DegToRadians)
          SurfaceTmp(SurfNum)%CosTilt=COS(SurfaceTmp(SurfNum)%Tilt*DegToRadians)
          SurfaceTmp(SurfNum)%SinTilt=SIN(SurfaceTmp(SurfNum)%Tilt*DegToRadians)

          SurfaceTmp(SurfNum)%Sides=4
          ALLOCATE(SurfaceTmp(SurfNum)%Vertex(SurfaceTmp(SurfNum)%Sides))

          CALL MakeRelativeRectangularVertices(BaseSurfNum,SurfNum,  &
                           XLLC+SurfaceTmp(Found)%Width+rNumericArgs(6),YLLC-rNumericArgs(8),-Depth,Length)

        ! Reset surface to be "detached"
        !    SurfaceTmp(SurfNum)%BaseSurfName='  '
        !    SurfaceTmp(SurfNum)%ZoneName='  '

          SurfaceTmp(SurfNum)%BaseSurf=0
          SurfaceTmp(SurfNum)%Zone=0

        ! and mirror
          IF (MakeMirroredAttachedShading) THEN
            CALL MakeMirrorSurface(SurfNum)
          END IF
        ELSE
          SurfNum=SurfNum-1
        ENDIF
      ENDIF

    ENDDO

  ENDDO

  RETURN

END SUBROUTINE GetSimpleShdSurfaceData

SUBROUTINE GetIntMassSurfaceData(ErrorsFound,SurfNum,TotIntMass)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Linda Lawrie
          !       DATE WRITTEN   May 2000
          !       MODIFIED       na
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! This subroutine gets the Internal Surface Data,
          ! checks it for errors, etc.

          ! METHODOLOGY EMPLOYED:
          ! na

          ! REFERENCES:
  ! Internal Mass Surface Definition
  !Surface:HeatTransfer:InternalMass,
  !       \note used to describe internal zone surface area that does not need to be part of geometric representation
  !  A1 , \field User Supplied Surface Name
  !       \type alpha
  !       \reference SurfaceNames
  !  A2 , \field Construction Name of the Surface
  !       \note To be matched with a construction in this input file
  !       \type object-list
  !       \object-list ConstructionNames
  !  A3 , \field Interior Environment
  !       \note Zone the surface is a part of
  !       \type object-list
  !       \object-list ZoneNames
  !  N1,  \field View factor to Person (to people?)
  !       \type real
  !       \note from the interior of the surface
  !  N2 ; \field Surface area
  !       \units m2

          ! USE STATEMENTS:
  USE DataIPShortCuts
  USE InputProcessor, ONLY: GetNumObjectsFound, GetObjectItem, FindItemInList, VerifyName
  USE Vectors

  IMPLICIT NONE    ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
  LOGICAL, INTENT(INOUT)      :: ErrorsFound       ! Error flag indicator (true if errors found)
  INTEGER, INTENT(INOUT)      :: SurfNum           ! Count of Current SurfaceNumber
  INTEGER, INTENT(IN)         :: TotIntMass        ! Number of Internal Mass Surfaces to obtain

          ! SUBROUTINE PARAMETER DEFINITIONS:
          ! na

          ! INTERFACE BLOCK SPECIFICATIONS
          ! na

          ! DERIVED TYPE DEFINITIONS
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
  INTEGER :: IOStat            ! IO Status when calling get input subroutine
  INTEGER :: SurfaceNumAlpha   ! Number of material alpha names being passed
  INTEGER :: SurfaceNumProp    ! Number of material properties being passed
  INTEGER :: ZoneNum           ! DO loop counter (zones)
  INTEGER :: Loop
  LOGICAL :: ErrorInName
  LOGICAL :: IsBlank

  cCurrentModuleObject='InternalMass'
  DO Loop=1,TotIntMass
    CALL GetObjectItem(cCurrentModuleObject,Loop,cAlphaArgs,SurfaceNumAlpha,  &
                   rNumericArgs,SurfaceNumProp,IOSTAT,  &
                   AlphaBlank=lAlphaFieldBlanks,NumBlank=lNumericFieldBlanks,  &
                   AlphaFieldnames=cAlphaFieldNames,NumericFieldNames=cNumericFieldNames)
    ErrorInName=.false.
    IsBlank=.false.
    CALL VerifyName(cAlphaArgs(1),SurfaceTmp%Name,SurfNum,ErrorInName,IsBlank,TRIM(cCurrentModuleObject)//' Name')
    IF (ErrorInName) THEN
      CALL ShowContinueError('...each surface name must not duplicate other surface names (of any type)')
      ErrorsFound=.true.
      CYCLE
    ENDIF

    SurfNum=SurfNum+1
    SurfaceTmp(SurfNum)%Name = cAlphaArgs(1)  ! Set the Surface Name in the Derived Type
    SurfaceTmp(SurfNum)%Class= SurfaceClass_IntMass
    SurfaceTmp(SurfNum)%HeatTransSurf=.true.
    SurfaceTmp(SurfNum)%Construction=FindIteminList(cAlphaArgs(2),Construct%Name,TotConstructs)

    IF(SurfaceTmp(SurfNum)%Construction == 0) THEN
      ErrorsFound = .true.
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                             '", '//TRIM(cAlphaFieldNames(2))//' not found='//TRIM(cAlphaArgs(2)))
    ELSEIF (Construct(SurfaceTmp(SurfNum)%Construction)%TypeIsWindow) THEN
      ErrorsFound = .true.
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                             '", invalid '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))// &
                             '" - has Window materials.')
    ELSE
      Construct(SurfaceTmp(SurfNum)%Construction)%IsUsed=.true.
      SurfaceTmp(SurfNum)%ConstructionStoredInputValue  = SurfaceTmp(SurfNum)%Construction
    END IF
    SurfaceTmp(SurfNum)%ZoneName=cAlphaArgs(3)
    ZoneNum=FindItemInList(SurfaceTmp(SurfNum)%ZoneName,Zone%Name,NumOfZones)

    IF (ZoneNum /= 0) THEN
      SurfaceTmp(SurfNum)%Zone = ZoneNum
    ELSE
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                             '", invalid '//TRIM(cAlphaFieldNames(3))//'="'//TRIM(cAlphaArgs(3))//'".')
      SurfaceTmp(SurfNum)%Class=SurfaceTmp(SurfNum)%Class+100
!      SurfaceTmp(SurfNum)%Class=0
      SurfaceTmp(SurfNum)%ZoneName='Unknown Zone'
      ErrorsFound=.true.
    ENDIF
    SurfaceTmp(SurfNum)%GrossArea=rNumericArgs(1)
    SurfaceTmp(SurfNum)%Area=SurfaceTmp(SurfNum)%GrossArea
    SurfaceTmp(SurfNum)%NetAreaShadowCalc = SurfaceTmp(SurfNum)%Area
    SurfaceTmp(SurfNum)%Width=SurfaceTmp(SurfNum)%Area
    SurfaceTmp(SurfNum)%Height=1.0d0
    SurfaceTmp(SurfNum)%Tilt=90.d0
    SurfaceTmp(SurfNum)%CosTilt=COS(90.d0*DegToRadians)
    SurfaceTmp(SurfNum)%SinTilt=SIN(90.d0*DegToRadians)
    SurfaceTmp(SurfNum)%Azimuth=0.0d0
    SurfaceTmp(SurfNum)%CosAzim=COS(0.0d0)
    SurfaceTmp(SurfNum)%SinAzim=SIN(0.0d0)
    ! Outward normal unit vector (pointing away from room)
    SurfaceTmp(SurfNum)%OutNormVec = SurfaceTmp(SurfNum)%lcsz
    SurfaceTmp(SurfNum)%ViewFactorSky=.5d0
    SurfaceTmp(SurfNum)%ExtSolar=.false.
    SurfaceTmp(SurfNum)%ExtWind=.false.
    SurfaceTmp(SurfNum)%BaseSurf = SurfNum
    SurfaceTmp(SurfNum)%BaseSurfName=SurfaceTmp(SurfNum)%Name
    SurfaceTmp(SurfNum)%ExtBoundCondName=SurfaceTmp(SurfNum)%Name
    SurfaceTmp(SurfNum)%ExtBoundCond=UnreconciledZoneSurface

  ENDDO

  RETURN

END SUBROUTINE GetIntMassSurfaceData

SUBROUTINE GetShadingSurfReflectanceData(ErrorsFound)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Fred Winkelmann
          !       DATE WRITTEN   Sept 2003
          !       MODIFIED       na
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! Gets data for a Shading Surface Reflectance object.  This is only called when the
          ! Solar Distribution is to be calculated for reflectances.

          ! METHODOLOGY EMPLOYED: na
          ! REFERENCES: na

          ! USE STATEMENTS:
  USE DataIPShortCuts
  USE InputProcessor, ONLY: GetNumObjectsFound, GetObjectItem, FindItemInList
  USE General, ONLY: RoundSigDigits

  IMPLICIT NONE    ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
  LOGICAL, INTENT(INOUT) :: ErrorsFound ! If errors found in input

          ! SUBROUTINE PARAMETER DEFINITIONS:
  CHARACTER(len=*), PARAMETER :: fmtA='(A)'
          ! INTERFACE BLOCK SPECIFICATIONS:na
          ! DERIVED TYPE DEFINITIONS:na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:

  INTEGER :: IOStat                   ! IO Status when calling get input subroutine
  INTEGER :: NumAlpha                 ! Number of alpha names being passed
  INTEGER :: NumProp                  ! Number of properties being passed
  INTEGER :: TotShadingSurfaceReflectance  ! Total Shading Surface Refleftance statements
  INTEGER :: Loop                     ! DO loop index
  INTEGER :: SurfNum                  ! Surface number
  INTEGER :: GlConstrNum              ! Glazing construction number
  LOGICAL :: WrongSurfaceType

  ! For shading surfaces, initialize value of reflectance values to default values. These values
  ! may be overridden below for shading surfaces with an associated Shading Surface Reflectance object.
  DO SurfNum = 1, TotSurfaces
      IF (.not. (SurfaceTmp(SurfNum)%Class == SurfaceClass_Shading .or.      &
                 SurfaceTmp(SurfNum)%Class == SurfaceClass_Detached_F .or.   &
                 SurfaceTmp(SurfNum)%Class == SurfaceClass_Detached_B .or.   &
                 SurfaceTmp(SurfNum)%Class == SurfaceClass_Overhang .or.     &
                 SurfaceTmp(SurfNum)%Class == SurfaceClass_Fin) ) CYCLE
      SurfaceTmp(SurfNum)%ShadowSurfDiffuseSolRefl  = 0.2d0
      SurfaceTmp(SurfNum)%ShadowSurfDiffuseVisRefl  = 0.2d0
      SurfaceTmp(SurfNum)%ShadowSurfGlazingFrac = 0.0d0
      SurfaceTmp(SurfNum)%ShadowSurfGlazingConstruct = 0
  END DO

  ! Get the total number of Shading Surface Reflectance objects
  cCurrentModuleObject='ShadingProperty:Reflectance'
  TotShadingSurfaceReflectance = GetNumObjectsFound(cCurrentModuleObject)
!  IF(TotShadingSurfaceReflectance.EQ.0) RETURN

  DO Loop = 1, TotShadingSurfaceReflectance

    CALL GetObjectItem(cCurrentModuleObject,Loop,cAlphaArgs,NumAlpha,rNumericArgs,NumProp,IOSTAT,  &
                   AlphaBlank=lAlphaFieldBlanks,NumBlank=lNumericFieldBlanks,  &
                   AlphaFieldnames=cAlphaFieldNames,NumericFieldNames=cNumericFieldNames)
    SurfNum = FindItemInList(cAlphaArgs(1),SurfaceTmp%Name,TotSurfaces)
    IF(SurfNum == 0) THEN
      CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(cAlphaArgs(1))//  &
                             '", invalid specification')
      CALL ShowContinueError('.. not found '//TRIM(cAlphaFieldNames(1))//'="'//trim(cAlphaArgs(1))//'".')
!      ErrorsFound =.true.
      CYCLE
    END IF

    ! Check that associated surface is a shading surface
    WrongSurfaceType = .FALSE.
    IF(SurfNum /= 0) THEN
      IF (.not. (SurfaceTmp(SurfNum)%Class == SurfaceClass_Shading .or.      &
                 SurfaceTmp(SurfNum)%Class == SurfaceClass_Detached_F .or.   &
                 SurfaceTmp(SurfNum)%Class == SurfaceClass_Detached_B .or.   &
                 SurfaceTmp(SurfNum)%Class == SurfaceClass_Overhang .or.     &
                 SurfaceTmp(SurfNum)%Class == SurfaceClass_Fin) ) WrongSurfaceType = .TRUE.
      IF(WrongSurfaceType) THEN
        CALL ShowSevereError('GetShadingSurfReflectanceData: '//TRIM(cCurrentModuleObject)//'="'//  &
                  TRIM(SurfaceTmp(SurfNum)%Name)//  &
                  '", surface is not a shading surface.')
        ErrorsFound = .TRUE.
        CYCLE
      END IF
    END IF

    ! If associated surface is a shading surface, set reflectance values
    SurfaceTmp(SurfNum)%ShadowSurfGlazingFrac = rNumericArgs(3)
    SurfaceTmp(SurfNum)%ShadowSurfDiffuseSolRefl  = (1.d0-rNumericArgs(3)) * rNumericArgs(1)
    SurfaceTmp(SurfNum)%ShadowSurfDiffuseVisRefl  = (1.d0-rNumericArgs(3)) * rNumericArgs(2)
    IF(rNumericArgs(3) > 0.0d0) THEN
      GlConstrNum = FindItemInList(cAlphaArgs(2),Construct%Name,TotConstructs)
      IF(GlConstrNum == 0) THEN
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
                           '", '//TRIM(cAlphaFieldNames(2))//' not found='//TRIM(cAlphaArgs(2)))
        ErrorsFound =.true.
      ELSE
        Construct(GlConstrNum)%IsUsed=.true.
      END IF
      SurfaceTmp(SurfNum)%ShadowSurfGlazingConstruct = GlConstrNum
    END IF
    SurfNum = FindItemInList('Mir-'//cAlphaArgs(1),SurfaceTmp%Name,TotSurfaces)
    IF (SurfNum == 0) CYCLE
    SurfaceTmp(SurfNum)%ShadowSurfGlazingFrac = rNumericArgs(3)
    SurfaceTmp(SurfNum)%ShadowSurfDiffuseSolRefl  = (1.d0-rNumericArgs(3)) * rNumericArgs(1)
    SurfaceTmp(SurfNum)%ShadowSurfDiffuseVisRefl  = (1.d0-rNumericArgs(3)) * rNumericArgs(2)
    IF(rNumericArgs(3) > 0.0d0) THEN
      GlConstrNum = FindItemInList(cAlphaArgs(2),Construct%Name,TotConstructs)
      IF(GlConstrNum /= 0) THEN
        Construct(GlConstrNum)%IsUsed=.true.
      END IF
      SurfaceTmp(SurfNum)%ShadowSurfGlazingConstruct = GlConstrNum
    END IF

  END DO  ! End of loop over Shading Surface Reflectance objects

  ! Write reflectance values to .eio file.
  Write(OutputFileInits,fmtA) '! <ShadingProperty Reflectance>,Shading Surface Name,Shading Type,Diffuse Solar Reflectance, '//  &
     'Diffuse Visible Reflectance,Surface Glazing Fraction,Surface Glazing Contruction'

  DO SurfNum = 1, TotSurfaces
    IF (.not. (SurfaceTmp(SurfNum)%Class == SurfaceClass_Shading .or.      &
               SurfaceTmp(SurfNum)%Class == SurfaceClass_Detached_F .or.   &
               SurfaceTmp(SurfNum)%Class == SurfaceClass_Detached_B .or.   &
               SurfaceTmp(SurfNum)%Class == SurfaceClass_Overhang .or.     &
               SurfaceTmp(SurfNum)%Class == SurfaceClass_Fin) ) CYCLE
    IF (SurfaceTmp(SurfNum)%ShadowSurfGlazingConstruct /= 0) THEN
      Write(OutputFileInits,'(A)') 'ShadingProperty Reflectance,'//trim(SurfaceTmp(SurfNum)%Name)//','//  &
         trim(cSurfaceClass(SurfaceTmp(SurfNum)%class))//','//  &
         trim(RoundSigDigits(SurfaceTmp(SurfNum)%ShadowSurfDiffuseSolRefl,2))//','//  &
         trim(RoundSigDigits(SurfaceTmp(SurfNum)%ShadowSurfDiffuseVisRefl,2))//','//  &
         trim(RoundSigDigits(SurfaceTmp(SurfNum)%ShadowSurfGlazingFrac,2))//','//  &
         trim(Construct(SurfaceTmp(SurfNum)%ShadowSurfGlazingConstruct)%Name)
    ELSE
      Write(OutputFileInits,'(A)') 'ShadingProperty Reflectance,'//trim(SurfaceTmp(SurfNum)%Name)//','//  &
         trim(cSurfaceClass(SurfaceTmp(SurfNum)%class))//','//  &
         trim(RoundSigDigits(SurfaceTmp(SurfNum)%ShadowSurfDiffuseSolRefl,2))//','//  &
         trim(RoundSigDigits(SurfaceTmp(SurfNum)%ShadowSurfDiffuseVisRefl,2))//','//  &
         trim(RoundSigDigits(SurfaceTmp(SurfNum)%ShadowSurfGlazingFrac,2))//', N/A'
    ENDIF
  END DO


  RETURN

END SUBROUTINE GetShadingSurfReflectanceData

SUBROUTINE GetHTSurfExtVentedCavityData(ErrorsFound )

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         BGriffith
          !       DATE WRITTEN   January 2005
          !       MODIFIED       na
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! load input data for Exterior Vented Cavity Special case for heat transfer surfaces

          ! METHODOLOGY EMPLOYED:
          ! usual E+ input processes

          ! REFERENCES:
          ! derived from SUBROUTINE GetTranspiredCollectorInput

          ! USE STATEMENTS:
  USE DataIPShortCuts
  USE InputProcessor,   ONLY: GetNumObjectsFound, GetObjectItem, GetObjectDefMaxArgs, FindItemInList , &
                              SameString, VerifyName
  USE General,          ONLY: TrimSigDigits

  IMPLICIT NONE ! Enforce explicit typing of all variables in this routine

       ! SUBROUTINE ARGUMENT DEFINITIONS:
  LOGICAL, INTENT(INOUT)      :: ErrorsFound       ! Error flag indicator (true if errors found)

          ! SUBROUTINE PARAMETER DEFINITIONS:
          ! na

          ! INTERFACE BLOCK SPECIFICATIONS:
          ! na

          ! DERIVED TYPE DEFINITIONS:
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:

  INTEGER                        :: Item    ! Item to be "gotten"
  INTEGER                        :: NumAlphas  ! Number of Alphas for each GetObjectItem call
  INTEGER                        :: NumNumbers ! Number of Numbers for each GetObjectItem call
  INTEGER                        :: MaxNumAlphas !argument for call to GetObjectDefMaxArgs
  INTEGER                        :: MaxNumNumbers !argument for call to GetObjectDefMaxArgs
  INTEGER                        :: Dummy !argument for call to GetObjectDefMaxArgs
  INTEGER                        :: IOStatus   ! Used in GetObjectItem
  INTEGER                        :: Found
  INTEGER                        :: AlphaOffset !local temp var
  CHARACTER(len=MaxNameLength)   :: Roughness
  INTEGER                        :: thisSurf  ! do loop counter
  REAL(r64)                      :: AvgAzimuth ! temp for error checking
  REAL(r64)                      :: AvgTilt    ! temp for error checking
  INTEGER                        :: SurfID  ! local surface "pointer"
  LOGICAL                        :: IsBlank
  LOGICAL                        :: ErrorInName

  cCurrentModuleObject='SurfaceProperty:ExteriorNaturalVentedCavity'
  CALL GetObjectDefMaxArgs(cCurrentModuleObject,Dummy, MaxNumAlphas,MaxNumNumbers)

  IF (MaxNumNumbers /= 8) THEN
    CALL ShowSevereError(TRIM(cCurrentModuleObject)//': Object Definition indicates '// &
                         'not = 8 Number Objects, Number Indicated='//  &
                         TRIM(TrimSigDigits(MaxNumNumbers)))
    ErrorsFound=.true.
  ENDIF

  TotExtVentCav = GetNumObjectsFound(cCurrentModuleObject)

  ALLOCATE(ExtVentedCavity(TotExtVentCav))

  DO Item=1,TotExtVentCav
    CALL GetObjectItem(cCurrentModuleObject,Item,cAlphaArgs,NumAlphas,rNumericArgs,NumNumbers,IOStatus,  &
                   AlphaBlank=lAlphaFieldBlanks,NumBlank=lNumericFieldBlanks,  &
                   AlphaFieldnames=cAlphaFieldNames,NumericFieldNames=cNumericFieldNames)
    ! first handle cAlphaArgs
    ErrorInName=.false.
    IsBlank=.false.
    CALL VerifyName(cAlphaArgs(1),ExtVentedCavity%Name,Item-1,ErrorInName,IsBlank,TRIM(cCurrentModuleObject)//' Name')
    IF (ErrorInName) THEN
      CALL ShowContinueError('...cannot not duplicate other names')
      ErrorsFound=.true.
      CYCLE
    ENDIF
    ExtVentedCavity(Item)%Name     = cAlphaArgs(1)

    ExtVentedCavity(Item)%OSCMName = cAlphaArgs(2)
    IF (.not. lAlphaFieldBlanks(2)) THEN
      Found = FindItemInList(ExtVentedCavity(Item)%OSCMName,OSCM%Name,TotOSCM)
      IF (Found == 0) THEN
          CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(ExtVentedCavity(Item)%Name)//  &
                               '", invalid '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))//'".')
          ErrorsFound=.true.
      ENDIF
    ELSE
      Found=0
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(ExtVentedCavity(Item)%Name)//  &
                           '", invalid '//TRIM(cAlphaFieldNames(2))//' cannot be blank.')
      ErrorsFound=.true.
    ENDIF
    ExtVentedCavity(Item)%OSCMPtr = Found

    Roughness = cAlphaArgs(3)
    !Select the correct Number for the associated ascii name for the roughness type
    IF (SameString(Roughness,'VeryRough'))    ExtVentedCavity(Item)%BaffleRoughness=VeryRough
    IF (SameString(Roughness,'Rough'))        ExtVentedCavity(Item)%BaffleRoughness=Rough
    IF (SameString(Roughness,'MediumRough'))  ExtVentedCavity(Item)%BaffleRoughness=MediumRough
    IF (SameString(Roughness,'MediumSmooth')) ExtVentedCavity(Item)%BaffleRoughness=MediumSmooth
    IF (SameString(Roughness,'Smooth'))       ExtVentedCavity(Item)%BaffleRoughness=Smooth
    IF (SameString(Roughness,'VerySmooth'))   ExtVentedCavity(Item)%BaffleRoughness=VerySmooth

    ! Was it set?
    IF (ExtVentedCavity(Item)%BaffleRoughness == 0) THEN
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(ExtVentedCavity(Item)%Name)//  &
                             '", invalid '//TRIM(cAlphaFieldNames(3))//'="'//TRIM(cAlphaArgs(3)))
      ErrorsFound=.true.
    ENDIF

    AlphaOffset = 3
    ExtVentedCavity(Item)%NumSurfs = NumAlphas - AlphaOffset
    IF (ExtVentedCavity(Item)%NumSurfs == 0) THEN
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(ExtVentedCavity(Item)%Name)//  &
                           '", no underlying surfaces specified. Must have at least one.')
      ErrorsFound = .true.
      CYCLE
    ENDIF
    ALLOCATE(ExtVentedCavity(Item)%SurfPtrs(ExtVentedCavity(Item)%NumSurfs))
    ExtVentedCavity(Item)%SurfPtrs = 0
    DO thisSurf = 1, ExtVentedCavity(Item)%NumSurfs
        Found = FindItemInList(cAlphaArgs(thisSurf + AlphaOffset), Surface%Name, TotSurfaces)
        If (Found == 0) Then
           CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(ExtVentedCavity(Item)%Name)//  &
                                '", invalid '//TRIM(cAlphaFieldNames(thisSurf + AlphaOffset))//  &
                                '="'//TRIM(cAlphaArgs(thisSurf + AlphaOffset)))
           ErrorsFound=.true.
           CYCLE
        ENDIF
        ! check that surface is appropriate, Heat transfer, Sun, Wind,
        IF (.not. surface(Found)%HeatTransSurf) then
            CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(ExtVentedCavity(Item)%Name)//  &
                                '", invalid '//TRIM(cAlphaFieldNames(thisSurf + AlphaOffset))//  &
                                '="'//TRIM(cAlphaArgs(thisSurf + AlphaOffset)))
            CALL ShowContinueError('...because it is not a Heat Transfer Surface.')
            ErrorsFound=.true.
            CYCLE
        ENDIF
        IF (.not. surface(found)%ExtSolar) then
            CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(ExtVentedCavity(Item)%Name)//  &
                                '", invalid '//TRIM(cAlphaFieldNames(thisSurf + AlphaOffset))//  &
                                '="'//TRIM(cAlphaArgs(thisSurf + AlphaOffset)))
            CALL ShowContinueError('...because it is not exposed to Sun.')
            ErrorsFound=.true.
            CYCLE
        ENDIF
        IF (.not. surface(found)%ExtWind) then
            CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(ExtVentedCavity(Item)%Name)//  &
                                '", invalid '//TRIM(cAlphaFieldNames(thisSurf + AlphaOffset))//  &
                                '="'//TRIM(cAlphaArgs(thisSurf + AlphaOffset)))
            CALL ShowContinueError('...because it is not exposed to Wind.')
            ErrorsFound=.true.
            CYCLE
        ENDIF
        If(surface(found)%ExtBoundCond /= OtherSideCondModeledExt) Then
            CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(ExtVentedCavity(Item)%Name)//  &
                                '", is invalid')
            CALL ShowContinueError('...because '//TRIM(cAlphaFieldNames(thisSurf + AlphaOffset))//  &
                                '="'//TRIM(cAlphaArgs(thisSurf + AlphaOffset))//'".')
            CALL ShowContinueError('...is not an OtherSideConditionedModel surface.')
            ErrorsFound=.true.
            CYCLE
        ENDIF
        ExtVentedCavity(Item)%SurfPtrs(thisSurf) = Found

        ! now set info in Surface structure
        Surface(Found)%ExtCavNum        = Item
        Surface(Found)%ExtCavityPresent = .true.

    ENDDO

    IF (ErrorsFound) CYCLE  ! previous inner do loop may have detected problems that need to be cycle'd again to avoid crash

    ! now that we should have all the surfaces, do some preperations and checks.

    ! are they all similar tilt and azimuth? Issue warnings so people can do it if they really want
    AvgAzimuth = SUM(Surface(ExtVentedCavity(Item)%SurfPtrs)%Azimuth * Surface(ExtVentedCavity(Item)%SurfPtrs)%Area) &
                /SUM(Surface(ExtVentedCavity(Item)%SurfPtrs)%Area)
    AvgTilt    = SUM(Surface(ExtVentedCavity(Item)%SurfPtrs)%Tilt * Surface(ExtVentedCavity(Item)%SurfPtrs)%Area) &
                /SUM(Surface(ExtVentedCavity(Item)%SurfPtrs)%Area)
    DO thisSurf = 1, ExtVentedCavity(Item)%NumSurfs
       SurfID = ExtVentedCavity(Item)%SurfPtrs(thisSurf)
       If (ABS(Surface(SurfID)%Azimuth - AvgAzimuth) > 15.d0 ) Then
            Call ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(ExtVentedCavity(Item)%Name)//  &
            ', Surface '//TRIM(Surface(SurfID)%name)//' has Azimuth different from others in '// &
            'the associated group.')
       ENDIF
       IF (ABS(Surface(SurfID)%Tilt - AvgTilt) > 10.d0 ) Then
            Call ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(ExtVentedCavity(Item)%Name)//  &
            ', Surface '//TRIM(Surface(SurfID)%name)//' has Tilt different from others in '// &
            'the associated group.')
       ENDIF

       !test that there are no windows.  Now allow windows
      ! If (Surface(SurfID)%GrossArea >  Surface(SurfID)%Area) Then
      !      Call ShowWarningError('Surface '//TRIM(Surface(SurfID)%name)//' has a subsurface whose area is not being ' &
      !         //'subtracted in the group of surfaces associated with '//TRIM(ExtVentedCavity(Item)%Name))
      ! endif

    ENDDO
    ExtVentedCavity(Item)%Tilt    = AvgTilt
    ExtVentedCavity(Item)%Azimuth = AvgAzimuth

    ! find area weighted centroid.
    ExtVentedCavity(Item)%Centroid%Z =   &
                SUM(Surface(ExtVentedCavity(Item)%SurfPtrs)%Centroid%Z*Surface(ExtVentedCavity(Item)%SurfPtrs)%Area) &
                            /SUM(Surface(ExtVentedCavity(Item)%SurfPtrs)%Area)

    !now handle rNumericArgs from input object
    ExtVentedCavity(Item)%Porosity      = rNumericArgs(1)
    ExtVentedCavity(Item)%LWEmitt       = rNumericArgs(2)
    ExtVentedCavity(Item)%SolAbsorp     = rNumericArgs(3)
    ExtVentedCavity(Item)%HdeltaNPL     = rNumericArgs(4)
    ExtVentedCavity(Item)%PlenGapThick  = rNumericArgs(5)
    IF (ExtVentedCavity(Item)%PlenGapThick <= 0.0d0) THEN
         CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(ExtVentedCavity(Item)%Name)//  &
                                '", invalid .')
         ErrorsFound=.true.
         CALL ShowContinueError('...because Plenum gap must be greater than Zero=['//  &
            TRIM(TrimSigDigits(rNumericArgs(5),2))//'].')
         CYCLE
    ENDIF
    ExtVentedCavity(Item)%AreaRatio     = rNumericArgs(6)
    ExtVentedCavity(Item)%Cv            = rNumericArgs(7)
    ExtVentedCavity(Item)%Cd            = rNumericArgs(8)

    ! Fill out data we now know
    ! sum areas of HT surface areas
    ExtVentedCavity(Item)%ProjArea      = SUM(Surface(ExtVentedCavity(Item)%SurfPtrs)%Area)
    IF (ExtVentedCavity(Item)%ProjArea <= 0.0d0) THEN
         CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(ExtVentedCavity(Item)%Name)//  &
                                '", invalid .')
         ErrorsFound=.true.
         CALL ShowContinueError('...because gross area of underlying surfaces must be greater than Zero=['//  &
            TRIM(TrimSigDigits(ExtVentedCavity(Item)%ProjArea,2))//'].')
         CYCLE
    endif
    ExtVentedCavity(Item)%ActualArea    = ExtVentedCavity(Item)%ProjArea * ExtVentedCavity(Item)%AreaRatio

    CALL SetupOutputVariable('Surface Exterior Cavity Baffle Surface Temperature [C]',ExtVentedCavity(Item)%Tbaffle, &
                               'System','Average',ExtVentedCavity(Item)%Name)
    CALL SetupOutputVariable('Surface Exterior Cavity Air Drybulb Temperature [C]',ExtVentedCavity(Item)%TAirCav, &
                               'System','Average',ExtVentedCavity(Item)%Name)
    CALL SetupOutputVariable('Surface Exterior Cavity Total Natural Ventilation Air Change Rate [ACH]', &
                              ExtVentedCavity(Item)%PassiveACH, &
                              'System','Average',ExtVentedCavity(Item)%Name)
    CALL SetupOutputVariable('Surface Exterior Cavity Total Natural Ventilation Mass Flow Rate [kg/s]', &
                              ExtVentedCavity(Item)%PassiveMdotVent, &
                               'System','Average',ExtVentedCavity(Item)%Name)
    CALL SetupOutputVariable('Surface Exterior Cavity Natural Ventilation from Wind Mass Flow Rate [kg/s]', &
                              ExtVentedCavity(Item)%PassiveMdotWind, &
                               'System','Average',ExtVentedCavity(Item)%Name)
    CALL SetupOutputVariable('Surface Exterior Cavity Natural Ventilation from Buoyancy Mass Flow Rate [kg/s]',  &
                               ExtVentedCavity(Item)%PassiveMdotTherm, &
                               'System','Average',ExtVentedCavity(Item)%Name)

  ENDDO

  RETURN

END SUBROUTINE GetHTSurfExtVentedCavityData

SUBROUTINE GetSurfaceHeatTransferAlgorithmOverrides(ErrorsFound)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         B. Griffith, portions from ApplyConvectionValue by Linda Lawrie
          !       DATE WRITTEN   July 2012
          !       MODIFIED       na
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! <description>

          ! METHODOLOGY EMPLOYED:
          ! <description>

          ! REFERENCES:
          ! na

          ! USE STATEMENTS:
  USE DataIPShortcuts
  USE InputProcessor,  ONLY: GetNumObjectsFound, GetObjectItem, FindItemInList
  USE DataSurfaces,    ONLY: Surface
  USE DataHeatBalance, ONLY: HeatTransferAlgosUsed, NumberOfHeatTransferAlgosUsed &
                             ,LowHConvLimit, HighHConvLimit
  USE General,         ONLY: RoundSigDigits

  USE DataHeatBalSurface ,ONLY:MaxSurfaceTempLimit
  IMPLICIT NONE ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
  LOGICAL, INTENT(INOUT) :: ErrorsFound

          ! SUBROUTINE PARAMETER DEFINITIONS:

  CHARACTER(len=*), PARAMETER :: fmtA="(A)"

          ! INTERFACE BLOCK SPECIFICATIONS:
          ! na

          ! DERIVED TYPE DEFINITIONS:
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
  INTEGER :: CountHTAlgoObjectsSingleSurf
  INTEGER :: CountHTAlgoObjectsMultiSurf
  INTEGER :: CountHTAlgoObjectsSurfList
  INTEGER :: IOStatus   ! Used in GetObjectItem
  LOGICAL :: ErrorsFoundSingleSurf = .FALSE.
  LOGICAL :: ErrorsFoundMultiSurf  = .FALSE.
  LOGICAL :: ErrorsFoundSurfList   = .FALSE.
  LOGICAL :: ErrorsFoundByConstruct= .FALSE.
  INTEGER :: tmpAlgoInput
  INTEGER :: Item
  INTEGER :: Item1
  INTEGER :: NumAlphas
  INTEGER :: NumNumbers
  INTEGER :: Found
  LOGICAL :: SurfacesOfType
  INTEGER :: SurfNum
!  INTEGER :: Index
  INTEGER, DIMENSION(:), ALLOCATABLE :: tmpHeatTransferAlgosUsed
  INTEGER :: NumEMPDMat
  INTEGER :: NumPCMat
  INTEGER :: NumVTCMat
  INTEGER :: NumHAMTMat1
  INTEGER :: NumHAMTMat2
  INTEGER :: NumHAMTMat3
  INTEGER :: NumHAMTMat4
  INTEGER :: NumHAMTMat5
  INTEGER :: NumHAMTMat6
  INTEGER :: SumHAMTMat
  LOGICAL :: msgneeded
  CHARACTER(len=MaxNameLength) :: AlgoName


  ! first initialize each heat transfer surface with the overall model type, array assignment
  Surface%HeatTransferAlgorithm  = HeatTransferAlgosUsed(1)
!

  cCurrentModuleObject = 'SurfaceProperty:HeatTransferAlgorithm'
  CountHTAlgoObjectsSingleSurf = GetNumObjectsFound(cCurrentModuleObject)


  cCurrentModuleObject = 'SurfaceProperty:HeatTransferAlgorithm'
  DO Item=1, CountHTAlgoObjectsSingleSurf
    CALL GetObjectItem(cCurrentModuleObject,Item,cAlphaArgs,NumAlphas,rNumericArgs,NumNumbers,IOStatus,  &
                   AlphaBlank=lAlphaFieldBlanks,NumBlank=lNumericFieldBlanks,  &
                   AlphaFieldnames=cAlphaFieldNames,NumericFieldNames=cNumericFieldNames)
    ErrorsFoundSingleSurf = .FALSE.
    Found = FindItemInList(cAlphaArgs(1), Surface%Name,  TotSurfaces)

    IF (Found == 0) Then
      Call ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM( cAlphaArgs(1))//  &
                                '", did not find matching surface.')
      ErrorsFoundSingleSurf = .TRUE.

    ENDIF

    SELECT CASE (cAlphaArgs(2))

    CASE ('CONDUCTIONTRANSFERFUNCTION')
      tmpAlgoInput = HeatTransferModel_CTF
    CASE ('MOISTUREPENETRATIONDEPTHCONDUCTIONTRANSFERFUNCTION')
      tmpAlgoInput = HeatTransferModel_EMPD
    CASE ('COMBINEDHEATANDMOISTUREFINITEELEMENT')
      tmpAlgoInput = HeatTransferModel_HAMT
    CASE ('CONDUCTIONFINITEDIFFERENCE')
      tmpAlgoInput = HeatTransferModel_CondFD
    CASE DEFAULT
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(cAlphaArgs(1))//  &
                             '", invalid '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2)))
      ErrorsFoundSingleSurf = .TRUE.
    END SELECT

    IF (.NOT. ErrorsFoundSingleSurf) THEN
      Surface(Found)%HeatTransferAlgorithm   = tmpAlgoInput

      IF (.NOT. ANY(HeatTransferAlgosUsed == tmpAlgoInput)) THEN ! add new algo
        ALLOCATE(tmpHeatTransferAlgosUsed(NumberOfHeatTransferAlgosUsed))
        tmpHeatTransferAlgosUsed = HeatTransferAlgosUsed
        NumberOfHeatTransferAlgosUsed = NumberOfHeatTransferAlgosUsed + 1
        DEALLOCATE(HeatTransferAlgosUsed)
        ALLOCATE(HeatTransferAlgosUsed(NumberOfHeatTransferAlgosUsed))
        HeatTransferAlgosUsed(1:NumberOfHeatTransferAlgosUsed-1) = tmpHeatTransferAlgosUsed
        HeatTransferAlgosUsed(NumberOfHeatTransferAlgosUsed) = tmpAlgoInput
        DEALLOCATE(tmpHeatTransferAlgosUsed)
      ENDIF

    ELSE
      ErrorsFound = .TRUE.
    ENDIF
  ENDDO  ! single surface heat transfer algorithm override


  cCurrentModuleObject = 'SurfaceProperty:HeatTransferAlgorithm:MultipleSurface'
  CountHTAlgoObjectsMultiSurf = GetNumObjectsFound(cCurrentModuleObject)

  DO Item=1, CountHTAlgoObjectsMultiSurf
    CALL GetObjectItem(cCurrentModuleObject,Item,cAlphaArgs,NumAlphas,rNumericArgs,NumNumbers,IOStatus,  &
                   AlphaBlank=lAlphaFieldBlanks,NumBlank=lNumericFieldBlanks,  &
                   AlphaFieldnames=cAlphaFieldNames,NumericFieldNames=cNumericFieldNames)
    ErrorsFoundMultiSurf = .FALSE.
    SELECT CASE (cAlphaArgs(3))

    CASE ('CONDUCTIONTRANSFERFUNCTION')
      tmpAlgoInput = HeatTransferModel_CTF
    CASE ('MOISTUREPENETRATIONDEPTHCONDUCTIONTRANSFERFUNCTION')
      tmpAlgoInput = HeatTransferModel_EMPD
    CASE ('COMBINEDHEATANDMOISTUREFINITEELEMENT')
      tmpAlgoInput = HeatTransferModel_HAMT
    CASE ('CONDUCTIONFINITEDIFFERENCE')
      tmpAlgoInput = HeatTransferModel_CondFD
    CASE DEFAULT
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(cAlphaArgs(1))//  &
                             '", invalid '//TRIM(cAlphaFieldNames(3))//'="'//TRIM(cAlphaArgs(3)))
      ErrorsFoundMultiSurf = .TRUE.
    END SELECT

    SELECT CASE(cAlphaArgs(2))

      CASE ('ALLEXTERIORSURFACES')
        SurfacesOfType=.false.
        DO SurfNum=1,TotSurfaces
          IF (.not. Surface(SurfNum)%HeatTransSurf) CYCLE
          IF (Surface(SurfNum)%ExtBoundCond > 0) CYCLE    ! Interior surfaces
          IF (Construct(Surface(SurfNum)%Construction)%TypeIsWindow) CYCLE
          SurfacesOfType=.true.
          Surface(SurfNum)%HeatTransferAlgorithm   = tmpAlgoInput
        ENDDO

      CASE ('ALLEXTERIORWALLS')
        SurfacesOfType=.false.
        DO SurfNum=1,TotSurfaces
          IF (.not. Surface(SurfNum)%HeatTransSurf) CYCLE
          IF (Surface(SurfNum)%ExtBoundCond > 0) CYCLE    ! Interior surfaces
          IF (.not. Surface(SurfNum)%Class == SurfaceClass_Wall) CYCLE
          IF (Construct(Surface(SurfNum)%Construction)%TypeIsWindow) CYCLE
          SurfacesOfType=.true.
          Surface(SurfNum)%HeatTransferAlgorithm   = tmpAlgoInput
       ENDDO

      CASE('ALLEXTERIORROOFS')
        SurfacesOfType=.false.
        DO SurfNum=1,TotSurfaces
          IF (.not. Surface(SurfNum)%HeatTransSurf) CYCLE
          IF (Surface(SurfNum)%ExtBoundCond > 0) CYCLE    ! Interior surfaces
          IF (.not. Surface(SurfNum)%Class == SurfaceClass_Roof) CYCLE
          IF (Construct(Surface(SurfNum)%Construction)%TypeIsWindow) CYCLE
          SurfacesOfType=.true.
          Surface(SurfNum)%HeatTransferAlgorithm   = tmpAlgoInput
        ENDDO

      CASE('ALLEXTERIORFLOORS')
        SurfacesOfType=.false.
        DO SurfNum=1,TotSurfaces
          IF (.not. Surface(SurfNum)%HeatTransSurf) CYCLE
          IF (Surface(SurfNum)%ExtBoundCond > 0) CYCLE    ! Interior surfaces
          IF (.not. Surface(SurfNum)%Class == SurfaceClass_Floor) CYCLE
          IF (Construct(Surface(SurfNum)%Construction)%TypeIsWindow) CYCLE
          SurfacesOfType=.true.
          Surface(SurfNum)%HeatTransferAlgorithm   = tmpAlgoInput
        ENDDO

      CASE ('ALLGROUNDCONTACTSURFACES')
        SurfacesOfType=.false.
        DO SurfNum=1,TotSurfaces
          IF (.not. Surface(SurfNum)%HeatTransSurf) CYCLE
          IF (Surface(SurfNum)%ExtBoundCond /= Ground) CYCLE    ! ground BC
          IF (Construct(Surface(SurfNum)%Construction)%TypeIsWindow) CYCLE
          SurfacesOfType=.true.
          Surface(SurfNum)%HeatTransferAlgorithm   = tmpAlgoInput
        ENDDO
      CASE ('ALLINTERIORSURFACES')
        SurfacesOfType=.false.
        DO SurfNum=1,TotSurfaces
          IF (.not. Surface(SurfNum)%HeatTransSurf) CYCLE
          IF (Surface(SurfNum)%ExtBoundCond <= 0) CYCLE    ! Exterior surfaces
          IF (Construct(Surface(SurfNum)%Construction)%TypeIsWindow) CYCLE
          SurfacesOfType=.true.
          Surface(SurfNum)%HeatTransferAlgorithm   = tmpAlgoInput
        ENDDO

      CASE ('ALLINTERIORWALLS')
        SurfacesOfType=.false.
        DO SurfNum=1,TotSurfaces
          IF (.not. Surface(SurfNum)%HeatTransSurf) CYCLE
          IF (Surface(SurfNum)%ExtBoundCond <= 0) CYCLE    ! Exterior surfaces
          IF (.not. Surface(SurfNum)%Class == SurfaceClass_Wall) CYCLE
          IF (Construct(Surface(SurfNum)%Construction)%TypeIsWindow) CYCLE
          SurfacesOfType=.true.
          Surface(SurfNum)%HeatTransferAlgorithm   = tmpAlgoInput
        ENDDO

      CASE('ALLINTERIORROOFS','ALLINTERIORCEILINGS')
        SurfacesOfType=.false.
        DO SurfNum=1,TotSurfaces
          IF (.not. Surface(SurfNum)%HeatTransSurf) CYCLE
          IF (Surface(SurfNum)%ExtBoundCond <= 0) CYCLE    ! Exterior surfaces
          IF (.not. Surface(SurfNum)%Class == SurfaceClass_Roof) CYCLE
          IF (Construct(Surface(SurfNum)%Construction)%TypeIsWindow) CYCLE
          SurfacesOfType=.true.
          Surface(SurfNum)%HeatTransferAlgorithm   = tmpAlgoInput
        ENDDO

      CASE('ALLINTERIORFLOORS')
        SurfacesOfType=.false.
        DO SurfNum=1,TotSurfaces
          IF (.not. Surface(SurfNum)%HeatTransSurf) CYCLE
          IF (Surface(SurfNum)%ExtBoundCond <= 0) CYCLE    ! Exterior surfaces
          IF (.not. Surface(SurfNum)%Class == SurfaceClass_Floor) CYCLE
          IF (Construct(Surface(SurfNum)%Construction)%TypeIsWindow) CYCLE
          SurfacesOfType=.true.
          Surface(SurfNum)%HeatTransferAlgorithm   = tmpAlgoInput
        ENDDO
      CASE DEFAULT
        SurfacesOfType=.false.
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(cAlphaArgs(1))//  &
                             '", invalid '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2)))
        ErrorsFoundMultiSurf = .TRUE.
    END SELECT

    IF (.not. SurfacesOfType) THEN
      CALL ShowWarningError('In '//TRIM(cCurrentModuleObject)//'="'//TRIM(cAlphaArgs(1))// &
         '", for Multiple Surface Assignment="'//trim(cAlphaArgs(2))//  &
         '", there were no surfaces of that type found for assignment.')
    ELSE
      IF (.NOT. ANY(HeatTransferAlgosUsed == tmpAlgoInput)) THEN ! add new algo
        ALLOCATE(tmpHeatTransferAlgosUsed(NumberOfHeatTransferAlgosUsed))
        tmpHeatTransferAlgosUsed = HeatTransferAlgosUsed
        NumberOfHeatTransferAlgosUsed = NumberOfHeatTransferAlgosUsed + 1
        DEALLOCATE(HeatTransferAlgosUsed)
        ALLOCATE(HeatTransferAlgosUsed(NumberOfHeatTransferAlgosUsed))
        HeatTransferAlgosUsed(1:NumberOfHeatTransferAlgosUsed-1) = tmpHeatTransferAlgosUsed
        HeatTransferAlgosUsed(NumberOfHeatTransferAlgosUsed) = tmpAlgoInput
        DEALLOCATE(tmpHeatTransferAlgosUsed)
      ENDIF
    ENDIF
    IF (ErrorsFoundMultiSurf) ErrorsFound = .TRUE.


  ENDDO ! multi surface heat transfer algo override


  cCurrentModuleObject = 'SurfaceProperty:HeatTransferAlgorithm:SurfaceList'
  CountHTAlgoObjectsSurfList = GetNumObjectsFound(cCurrentModuleObject)
  DO Item=1, CountHTAlgoObjectsSurfList
    CALL GetObjectItem(cCurrentModuleObject,Item,cAlphaArgs,NumAlphas,rNumericArgs,NumNumbers,IOStatus,  &
                   AlphaBlank=lAlphaFieldBlanks,NumBlank=lNumericFieldBlanks,  &
                   AlphaFieldnames=cAlphaFieldNames,NumericFieldNames=cNumericFieldNames)
    ErrorsFoundSurfList = .FALSE.
    SELECT CASE (cAlphaArgs(2))

    CASE ('CONDUCTIONTRANSFERFUNCTION')
      tmpAlgoInput = HeatTransferModel_CTF
    CASE ('MOISTUREPENETRATIONDEPTHCONDUCTIONTRANSFERFUNCTION')
      tmpAlgoInput = HeatTransferModel_EMPD
    CASE ('COMBINEDHEATANDMOISTUREFINITEELEMENT')
      tmpAlgoInput = HeatTransferModel_HAMT
    CASE ('CONDUCTIONFINITEDIFFERENCE')
      tmpAlgoInput = HeatTransferModel_CondFD
    CASE DEFAULT
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(cAlphaArgs(1))//  &
                             '", invalid '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2)))
      ErrorsFoundSurfList = .TRUE.
    END SELECT


    Do item1 = 3, NumAlphas

      Found = FinditemInList(cAlphaArgs(item1), Surface%Name,  TotSurfaces)

      IF (Found == 0) Then
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM( cAlphaArgs(1))//  &
                                '", did not find matching surface.')
        CALL ShowContinueError('Name of surface not found = "'//TRIM(cAlphaArgs(item1))//'"')
        ErrorsFoundSurfList = .TRUE.

      ENDIF

      IF (.NOT. ErrorsFoundSurfList) THEN
        Surface(Found)%HeatTransferAlgorithm   = tmpAlgoInput
        IF (.NOT. ANY(HeatTransferAlgosUsed == tmpAlgoInput)) THEN ! add new algo
          ALLOCATE(tmpHeatTransferAlgosUsed(NumberOfHeatTransferAlgosUsed))
          tmpHeatTransferAlgosUsed = HeatTransferAlgosUsed
          NumberOfHeatTransferAlgosUsed = NumberOfHeatTransferAlgosUsed + 1
          DEALLOCATE(HeatTransferAlgosUsed)
          ALLOCATE(HeatTransferAlgosUsed(NumberOfHeatTransferAlgosUsed))
          HeatTransferAlgosUsed(1:NumberOfHeatTransferAlgosUsed-1) = tmpHeatTransferAlgosUsed
          HeatTransferAlgosUsed(NumberOfHeatTransferAlgosUsed) = tmpAlgoInput
          DEALLOCATE(tmpHeatTransferAlgosUsed)
        ENDIF
      ELSE
        ErrorsFound = .TRUE.
      ENDIF

    ENDDO

  ENDDO

  cCurrentModuleObject = 'SurfaceProperty:HeatTransferAlgorithm:Construction'
  CountHTAlgoObjectsSurfList = GetNumObjectsFound(cCurrentModuleObject)
  DO Item=1, CountHTAlgoObjectsSurfList
    CALL GetObjectItem(cCurrentModuleObject,Item,cAlphaArgs,NumAlphas,rNumericArgs,NumNumbers,IOStatus,  &
                   AlphaBlank=lAlphaFieldBlanks,NumBlank=lNumericFieldBlanks,  &
                   AlphaFieldnames=cAlphaFieldNames,NumericFieldNames=cNumericFieldNames)
    ErrorsFoundByConstruct = .FALSE.
    SELECT CASE (cAlphaArgs(2))

    CASE ('CONDUCTIONTRANSFERFUNCTION')
      tmpAlgoInput = HeatTransferModel_CTF
    CASE ('MOISTUREPENETRATIONDEPTHCONDUCTIONTRANSFERFUNCTION')
      tmpAlgoInput = HeatTransferModel_EMPD
    CASE ('COMBINEDHEATANDMOISTUREFINITEELEMENT')
      tmpAlgoInput = HeatTransferModel_HAMT
    CASE ('CONDUCTIONFINITEDIFFERENCE')
      tmpAlgoInput = HeatTransferModel_CondFD
    CASE DEFAULT
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(cAlphaArgs(1))//  &
                             '", invalid '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2)))
      ErrorsFoundByConstruct = .TRUE.
    END SELECT

    Found = 0
    Found = FindItemInList(cAlphaArgs(3), Construct%Name,  TotConstructs )
    IF (Found == 0) THEN
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(cAlphaArgs(1))//  &
                             '", invalid '//TRIM(cAlphaFieldNames(3))//'="'//TRIM(cAlphaArgs(3)))
      ErrorsFoundByConstruct = .TRUE.
    ENDIF

    IF (.NOT. ErrorsFoundByConstruct ) THEN
      DO item1=1, TotSurfaces
        IF (Surface(item1)%Construction == Found) THEN
          Surface(item1)%HeatTransferAlgorithm   = tmpAlgoInput
          IF (.NOT. ANY(HeatTransferAlgosUsed == tmpAlgoInput)) THEN ! add new algo
            ALLOCATE(tmpHeatTransferAlgosUsed(NumberOfHeatTransferAlgosUsed))
            tmpHeatTransferAlgosUsed = HeatTransferAlgosUsed
            NumberOfHeatTransferAlgosUsed = NumberOfHeatTransferAlgosUsed + 1
            DEALLOCATE(HeatTransferAlgosUsed)
            ALLOCATE(HeatTransferAlgosUsed(NumberOfHeatTransferAlgosUsed))
            HeatTransferAlgosUsed(1:NumberOfHeatTransferAlgosUsed-1) = tmpHeatTransferAlgosUsed
            HeatTransferAlgosUsed(NumberOfHeatTransferAlgosUsed) = tmpAlgoInput
            DEALLOCATE(tmpHeatTransferAlgosUsed)
          ENDIF
        ENDIF
      ENDDO
    ENDIF
  ENDDO

  ! test for missing materials for algorithms selected
  NumEMPDMat=GetNumObjectsFound('MaterialProperty:MoisturePenetrationDepth:Settings')
  NumPCMat=GetNumObjectsFound('MaterialProperty:PhaseChange') ! needs detailed algo
  NumVTCMat=GetNumObjectsFound('MaterialProperty:VariableThermalConductivity')
  NumHAMTMat1=GetNumObjectsFound('MaterialProperty:HeatAndMoistureTransfer:Settings')
  NumHAMTMat2=GetNumObjectsFound('MaterialProperty:HeatAndMoistureTransfer:SorptionIsotherm')
  NumHAMTMat3=GetNumObjectsFound('MaterialProperty:HeatAndMoistureTransfer:Suction')
  NumHAMTMat4=GetNumObjectsFound('MaterialProperty:HeatAndMoistureTransfer:Redistribution')
  NumHAMTMat5=GetNumObjectsFound('MaterialProperty:HeatAndMoistureTransfer:Diffusion')
  NumHAMTMat6=GetNumObjectsFound('MaterialProperty:HeatAndMoistureTransfer:ThermalConductivity')
  SumHAMTMat=NumHAMTMat1+NumHAMTMat2+NumHAMTMat3+NumHAMTMat4+NumHAMTMat5+NumHAMTMat6
  msgneeded=.false.

  IF (NumEMPDMat > 0 .AND. .NOT. ANY(HeatTransferAlgosUsed == HeatTransferModel_EMPD)) THEN
    CALL ShowWarningError('The input file includes '// &
           TRIM(RoundSigDigits(NumEMPDMat))//' MaterialProperty:MoisturePenetrationDepth:Settings objects' &
           // ' but the moisture penetration depth algorithm is not used anywhere.')
    msgneeded=.true.
  ENDIF
  IF (NumPCMat > 0 .AND. .NOT. ANY(HeatTransferAlgosUsed == HeatTransferModel_CondFD)) THEN
    CALL ShowWarningError('The input file includes '// &
        TRIM(RoundSigDigits(NumPCMat))//' MaterialProperty:PhaseChange objects' &
        // ' but the conduction finite difference algorithm is not used anywhere.')
    msgneeded=.true.
  ENDIF
  IF (NumVTCMat > 0 .AND. .NOT. ANY(HeatTransferAlgosUsed == HeatTransferModel_CondFD)) THEN
    CALL ShowWarningError('The input file includes '// &
        TRIM(RoundSigDigits(NumVTCMat))//' MaterialProperty:VariableThermalConductivity objects' &
        // ' but the conduction finite difference algorithm is not used anywhere.')
    msgneeded=.true.
  ENDIF
  IF (SumHAMTMat > 0 .AND. .NOT. ANY(HeatTransferAlgosUsed == HeatTransferModel_HAMT )) THEN
    CALL ShowWarningError('The input file includes '// &
        trim(RoundSigDigits(SumHAMTMat))//' MaterialProperty:HeatAndMoistureTransfer:* objects' &
        // ' but the combined heat and moisture finite difference algorithm is not used anywhere.')
    msgneeded=.true.
  ENDIF
  IF (msgneeded) THEN
    CALL ShowContinueError('Previous materials will be ignored due to HeatBalanceAlgorithm choice.')
  ENDIF
  msgneeded = .FALSE.
  IF (NumEMPDMat == 0 .AND. ANY(HeatTransferAlgosUsed == HeatTransferModel_EMPD)) THEN
    CALL ShowWarningError('The moisture penetration depth conduction transfer function algorithm is used' &
               // ' but the input file includes no MaterialProperty:MoisturePenetrationDepth:Settings objects.')
    msgneeded=.TRUE.
  ENDIF
  IF (SumHAMTMat == 0 .AND. ANY(HeatTransferAlgosUsed == HeatTransferModel_HAMT ) ) THEN
    CALL ShowWarningError('The combined heat and moisture finite element algorithm is used but the input file includes '// &
                            ' no MaterialProperty:HeatAndMoistureTransfer:* objects.')
    msgneeded=.TRUE.
  ENDIF
  IF (msgneeded) THEN
    CALL ShowContinueError('Certain materials objects are necessary to achieve proper results with the heat transfer ' &
                            // 'algorithm(s) selected.')
  ENDIF


     ! Write Solution Algorithm to the initialization output file for User Verification
   Write(OutputFileInits,fmtA) '! <Surface Heat Transfer Algorithm>, Value {CTF - ConductionTransferFunction | '//  &
           'EMPD - MoisturePenetrationDepthConductionTransferFunction | '// &
           'CondFD - ConductionFiniteDifference | '// &
           'HAMT - CombinedHeatAndMoistureFiniteElement} - Description,Inside Surface Max Temperature Limit{C}, ' // &
           'Surface Convection Coefficient Lower Limit {W/m2-K}, Surface Convection Coefficient Upper Limit {W/m2-K}'

   DO item1 = 1, NumberOfHeatTransferAlgosUsed
     AlgoName = ' '
     SELECT CASE (HeatTransferAlgosUsed(item1))

     CASE (HeatTransferModel_CTF)
       AlgoName = 'CTF - ConductionTransferFunction'
     CASE (HeatTransferModel_CondFD)
       AlgoName = 'CondFD - ConductionFiniteDifference'
     CASE (HeatTransferModel_EMPD)
       AlgoName = 'EMPD - MoisturePenetrationDepthConductionTransferFunction'
     CASE (HeatTransferModel_HAMT)
       AlgoName = 'HAMT - CombinedHeatAndMoistureFiniteElement'
     END SELECT

     WRITE(OutputFileInits,725) TRIM(AlgoName),TRIM(RoundSigDigits(MaxSurfaceTempLimit,0)), &
            TRIM(RoundSigDigits(LowHConvLimit, 2)), TRIM(RoundSigDigits(HighHConvLimit, 1))
   ENDDO

   725 Format('Surface Heat Transfer Algorithm, ',A,',',A, ',', A, ',', A)

   !Assign model type to windows, shading surfaces, and TDDs
   DO item=1, TotSurfaces
     IF (Surface(item)%Class == SurfaceClass_Window .OR. &
         Surface(item)%Class == SurfaceClass_GlassDoor) THEN
       ! todo, add complex fenestration switch  HeatTransferModel_ComplexFenestration
       IF (SurfaceWindow(item)%WindowModelType == WindowBSDFModel) THEN
         Surface(item)%HeatTransferAlgorithm = HeatTransferModel_ComplexFenestration
       ELSE
         Surface(item)%HeatTransferAlgorithm = HeatTransferModel_Window5
       ENDIF
     ENDIF
     IF (Surface(item)%Class == SurfaceClass_Detached_B .OR. &
         Surface(item)%Class == SurfaceClass_Detached_F .OR. &
         Surface(item)%Class == SurfaceClass_Shading  .OR. &
         Surface(item)%Class == SurfaceClass_Overhang .OR. &
         Surface(item)%Class == SurfaceClass_Fin) THEN
       Surface(item)%HeatTransferAlgorithm = HeatTransferModel_None
     ENDIF
     IF ( Surface(item)%Class == SurfaceClass_TDD_Diffuser) THEN
       Surface(item)%HeatTransferAlgorithm = HeatTransferModel_TDD
     ENDIF

   ENDDO


  RETURN

END SUBROUTINE GetSurfaceHeatTransferAlgorithmOverrides

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

SUBROUTINE ReverseAndRecalculate(SurfNum,NSides,SurfAzimuth,SurfTilt)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Linda Lawrie
          !       DATE WRITTEN   February 2011
          !       MODIFIED       na
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! This routine reverses the vertices for a surface (needed when roof/floor is upside down)
          ! and recalculates the azimuth, etc for the surface.

          ! METHODOLOGY EMPLOYED:
          ! na

          ! REFERENCES:
          ! na

          ! USE STATEMENTS:
  USE Vectors
  USE General, ONLY: RoundSigDigits

  IMPLICIT NONE ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
  INTEGER, INTENT(IN) :: SurfNum   ! Surface number for the surface
  INTEGER, INTENT(IN) :: NSides    ! number of sides to surface
  REAL(r64), INTENT(INOUT) :: SurfAzimuth ! Surface Facing angle (will be 0 for roofs/floors)
  REAL(r64), INTENT(INOUT) :: SurfTilt    ! Surface tilt (

          ! SUBROUTINE PARAMETER DEFINITIONS:
  character(len=*), parameter :: fmt3="(A,I5,A,3(1x,f18.13))"
  character(len=*), parameter :: RoutineName='ReverseAndRecalculate: '

          ! INTERFACE BLOCK SPECIFICATIONS:
          ! na

          ! DERIVED TYPE DEFINITIONS:
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    INTEGER :: N ! Loop Control
    INTEGER :: RevPtr ! pointer for reversing vertices
    TYPE(vector), DIMENSION(NSides) :: Vertices    ! Vertices, in specified order
    CHARACTER(len=10) :: TiltString

    DO N=1,NSides
      Vertices(N)=SurfaceTmp(SurfNum)%Vertex(N)
    ENDDO
    RevPtr=NSides
    DO N=1,NSides
      SurfaceTmp(SurfNum)%Vertex(N)=Vertices(RevPtr)
      RevPtr=RevPtr-1
    ENDDO

    write(outputfiledebug,*) 'Reversing Surface Name='//trim(surfacetmp(surfnum)%Name)
    do N=1,nsides
      write(outputfiledebug,fmt3) 'side=',n,' abs coord vertex=',surfacetmp(surfnum)%vertex(n)%x,  &
         surfacetmp(surfnum)%vertex(n)%y,surfacetmp(surfnum)%vertex(n)%z
    enddo

    CALL CreateNewellSurfaceNormalVector(SurfaceTmp(SurfNum)%Vertex,SurfaceTmp(SurfNum)%Sides,  &
       SurfaceTmp(SurfNum)%NewellSurfaceNormalVector)
    CALL DetermineAzimuthAndTilt(SurfaceTmp(SurfNum)%Vertex,SurfaceTmp(SurfNum)%Sides,SurfAzimuth,SurfTilt,  &
                                 SurfaceTmp(SurfNum)%lcsx,SurfaceTmp(SurfNum)%lcsy,SurfaceTmp(SurfNum)%lcsz, &
                                 SurfaceTmp(SurfNum)%GrossArea,SurfaceTmp(SurfNum)%NewellSurfaceNormalVector)
    IF (SurfaceTmp(SurfNum)%Class == SurfaceClass_Roof .and. SurfTilt > 80.0d0) THEN
      TiltString=RoundSigDigits(SurfTilt,1)
      CALL ShowWarningError(RoutineName//'Roof/Ceiling is still upside down! Tilt angle=['//TRIM(TiltString)//  &
           '], should be near 0, please fix manually.')
    ENDIF
    IF (SurfaceTmp(SurfNum)%Class == SurfaceClass_Floor .and. SurfTilt < 158.2d0) THEN  ! 40% grade!
      CALL ShowWarningError(RoutineName//'Floor is still upside down! Tilt angle=['//TRIM(TiltString)//  &
         '], should be near 180, please fix manually.')
    ENDIF

  RETURN

END SUBROUTINE ReverseAndRecalculate

SUBROUTINE MakeMirrorSurface(SurfNum)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Linda Lawrie
          !       DATE WRITTEN   June 2002
          !       MODIFIED       na
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! This subroutine creates a "mirror" surface using the indicated surface.
          ! This is the simple approach for bi-directional shading devices.  If, perchance,
          ! the user has already taken care of this (e.g. fins in middle of wall), there will
          ! be extra shading devices shown.

          ! METHODOLOGY EMPLOYED:
          ! Reverse the vertices in the original surface.  Add "bi" to name.

          ! REFERENCES:
          ! na

          ! USE STATEMENTS:
  USE Vectors

  IMPLICIT NONE    ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
  INTEGER, INTENT(INOUT) :: SurfNum  ! In=>Surface to Mirror, Out=>new Surface index

          ! SUBROUTINE PARAMETER DEFINITIONS:
          ! na

          ! INTERFACE BLOCK SPECIFICATIONS
          ! na

          ! DERIVED TYPE DEFINITIONS
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
  INTEGER Vert
  INTEGER NVert
  REAL(r64) SurfWorldAz
  REAL(r64) SurfTilt
  INTEGER N
!  TYPE (Vector) :: temp1

  NVert=SurfaceTmp(SurfNum)%Sides
  ALLOCATE(SurfaceTmp(SurfNum+1)%Vertex(NVert))
! doesn't work when Vertex are pointers  SurfaceTmp(SurfNum+1)=SurfaceTmp(SurfNum)
  SurfaceTmp(SurfNum+1)%Name=SurfaceTmp(SurfNum)%Name
  SurfaceTmp(SurfNum+1)%Construction=SurfaceTmp(SurfNum)%Construction
  SurfaceTmp(SurfNum+1)%ConstructionStoredInputValue=SurfaceTmp(SurfNum)%ConstructionStoredInputValue
  SurfaceTmp(SurfNum+1)%Class=SurfaceTmp(SurfNum)%Class
  SurfaceTmp(SurfNum+1)%GrossArea=SurfaceTmp(SurfNum)%GrossArea
  SurfaceTmp(SurfNum+1)%Area=SurfaceTmp(SurfNum)%Area
  SurfaceTmp(SurfNum+1)%Azimuth=SurfaceTmp(SurfNum)%Azimuth
  SurfaceTmp(SurfNum+1)%Height=SurfaceTmp(SurfNum)%Height
  SurfaceTmp(SurfNum+1)%Reveal=SurfaceTmp(SurfNum)%Reveal
  SurfaceTmp(SurfNum+1)%Shape=SurfaceTmp(SurfNum)%Shape
  SurfaceTmp(SurfNum+1)%Sides=SurfaceTmp(SurfNum)%Sides
  SurfaceTmp(SurfNum+1)%Tilt=SurfaceTmp(SurfNum)%Tilt
  SurfaceTmp(SurfNum+1)%Width=SurfaceTmp(SurfNum)%Width
  SurfaceTmp(SurfNum+1)%HeatTransSurf=SurfaceTmp(SurfNum)%HeatTransSurf
  SurfaceTmp(SurfNum+1)%BaseSurfName=SurfaceTmp(SurfNum)%BaseSurfName
  SurfaceTmp(SurfNum+1)%BaseSurf=SurfaceTmp(SurfNum)%BaseSurf
  SurfaceTmp(SurfNum+1)%ZoneName=SurfaceTmp(SurfNum)%ZoneName
  SurfaceTmp(SurfNum+1)%Zone=SurfaceTmp(SurfNum)%Zone
  SurfaceTmp(SurfNum+1)%ExtBoundCondName=SurfaceTmp(SurfNum)%ExtBoundCondName
  SurfaceTmp(SurfNum+1)%ExtBoundCond=SurfaceTmp(SurfNum)%ExtBoundCond
  SurfaceTmp(SurfNum+1)%ExtSolar=SurfaceTmp(SurfNum)%ExtSolar
  SurfaceTmp(SurfNum+1)%ExtWind=SurfaceTmp(SurfNum)%ExtWind
  SurfaceTmp(SurfNum+1)%ViewFactorGround=SurfaceTmp(SurfNum)%ViewFactorGround
  SurfaceTmp(SurfNum+1)%ViewFactorSky=SurfaceTmp(SurfNum)%ViewFactorSky
  SurfaceTmp(SurfNum+1)%ViewFactorGroundIR=SurfaceTmp(SurfNum)%ViewFactorGroundIR
  SurfaceTmp(SurfNum+1)%ViewFactorSkyIR=SurfaceTmp(SurfNum)%ViewFactorSkyIR
  SurfaceTmp(SurfNum+1)%SchedShadowSurfIndex=SurfaceTmp(SurfNum)%SchedShadowSurfIndex
  SurfaceTmp(SurfNum+1)%ShadowSurfSchedVaries=SurfaceTmp(SurfNum)%ShadowSurfSchedVaries
  SurfaceTmp(SurfNum+1)%SchedMinValue=SurfaceTmp(SurfNum)%SchedMinValue
  SurfaceTmp(SurfNum+1)%IsTransparent=SurfaceTmp(SurfNum)%IsTransparent
  SurfaceTmp(SurfNum+1)%ShadowingSurf=SurfaceTmp(SurfNum)%ShadowingSurf
  SurfaceTmp(SurfNum+1)%MaterialMovInsulExt=SurfaceTmp(SurfNum)%MaterialMovInsulExt
  SurfaceTmp(SurfNum+1)%MaterialMovInsulInt=SurfaceTmp(SurfNum)%MaterialMovInsulInt
  SurfaceTmp(SurfNum+1)%SchedMovInsulExt=SurfaceTmp(SurfNum)%SchedMovInsulExt
  SurfaceTmp(SurfNum+1)%SchedMovInsulInt=SurfaceTmp(SurfNum)%SchedMovInsulInt
  SurfaceTmp(SurfNum+1)%WindowShadingControlPtr=SurfaceTmp(SurfNum)%WindowShadingControlPtr
  SurfaceTmp(SurfNum+1)%ShadedConstruction=SurfaceTmp(SurfNum)%ShadedConstruction
  SurfaceTmp(SurfNum+1)%FrameDivider=SurfaceTmp(SurfNum)%FrameDivider
  SurfaceTmp(SurfNum+1)%Multiplier=SurfaceTmp(SurfNum)%Multiplier
  SurfaceTmp(SurfNum+1)%NetAreaShadowCalc=SurfaceTmp(SurfNum)%NetAreaShadowCalc
  SurfaceTmp(SurfNum+1)%Perimeter=SurfaceTmp(SurfNum)%Perimeter

  DO Vert=1,SurfaceTmp(SurfNum)%Sides
    SurfaceTmp(SurfNum+1)%Vertex(Vert)=SurfaceTmp(SurfNum)%Vertex(NVert)
    NVert=NVert-1
  ENDDO
  SurfNum=SurfNum+1
  SurfaceTmp(SurfNum)%Name='Mir-'//TRIM(SurfaceTmp(SurfNum-1)%Name)

  ! TH 3/26/2010
  SurfaceTmp(SurfNum)%MirroredSurf = .TRUE.

  IF (SurfaceTmp(SurfNum)%Sides > 2) THEN
    CALL CreateNewellAreaVector(SurfaceTmp(SurfNum)%Vertex,SurfaceTmp(SurfNum)%Sides,SurfaceTmp(surfnum)%NewellAreaVector)
    SurfaceTmp(SurfNum)%GrossArea=VecLength(SurfaceTmp(surfnum)%NewellAreaVector)
    SurfaceTmp(SurfNum)%Area=SurfaceTmp(SurfNum)%GrossArea
    SurfaceTmp(SurfNum)%NetAreaShadowCalc = SurfaceTmp(SurfNum)%Area
    CALL CreateNewellSurfaceNormalVector(SurfaceTmp(SurfNum)%Vertex,SurfaceTmp(SurfNum)%Sides,  &
       SurfaceTmp(surfnum)%NewellSurfaceNormalVector)
    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)
    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)
      ! 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

    ! 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)
  ENDIF

  RETURN

END SUBROUTINE MakeMirrorSurface

SUBROUTINE GetWindowShadingControlData(ErrorsFound)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Fred Winkelmann
          !       DATE WRITTEN   November 1998
          !       MODIFIED       Aug 2001 (FW): add handling of new ShadingControlIsScheduled
          !                      and GlareControlIsActive fields
          !                      Nov 2001 (FW): add ShadingDevice as alternative to ShadedConstruction
          !                      Dec 2001 (FW): add slat angle controls for blinds
          !                      Aug 2002 (FW): add Setpoint2; check that specified control type is legal
          !                      Feb 2003 (FW): add error if Material Name of Shading Device is used with
          !                        Shading Type = BetweenGlassShade or BetweenGlassBlind
          !                      Dec 2003 (FW): improve BetweenGlassBlind error messages
          !                      Feb 2009 (BG): improve error checking for OnIfScheduleAllows
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! Reads in the window shading control information
          ! from the input data file, interprets it and puts it in the derived type

          ! METHODOLOGY EMPLOYED:

          ! REFERENCES:

          ! USE STATEMENTS:
  USE DataIPShortCuts
  USE InputProcessor, ONLY: GetNumObjectsFound, GetObjectItem, FindItemInList, VerifyName
  USE ScheduleManager, ONLY: GetScheduleIndex

  IMPLICIT NONE    ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
  LOGICAL, INTENT(INOUT) :: ErrorsFound ! If errors found in input

          ! SUBROUTINE PARAMETER DEFINITIONS:
  INTEGER, PARAMETER :: NumValidShadingTypes=8
  CHARACTER(len=*), PARAMETER, DIMENSION(NumValidShadingTypes) :: cValidShadingTypes=(/  &
                'INTERIORSHADE    ',  &
                'EXTERIORSHADE    ',  &
                'EXTERIORSCREEN   ',  &
                'INTERIORBLIND    ',  &
                'EXTERIORBLIND    ',  &
                'BETWEENGLASSSHADE',  &
                'BETWEENGLASSBLIND',  &
                'SWITCHABLEGLAZING'/)
  INTEGER, PARAMETER, DIMENSION(NumValidShadingTypes) :: ValidShadingTypes=(/  &
       WSC_ST_InteriorShade     , &
       WSC_ST_ExteriorShade     , &
       WSC_ST_ExteriorScreen    , &
       WSC_ST_InteriorBlind     , &
       WSC_ST_ExteriorBlind     , &
       WSC_ST_BetweenGlassShade , &
       WSC_ST_BetweenGlassBlind , &
       WSC_ST_SwitchableGlazing /)

  INTEGER, PARAMETER :: NumValidWindowShadingControlTypes=21
  CHARACTER(len=*), PARAMETER, DIMENSION(NumValidWindowShadingControlTypes) :: cValidWindowShadingControlTypes=(/  &
       'ALWAYSON                                      ', &
       'ALWAYSOFF                                     ', &
       'ONIFSCHEDULEALLOWS                            ', &
       'ONIFHIGHSOLARONWINDOW                         ', &
       'ONIFHIGHHORIZONTALSOLAR                       ', &
       'ONIFHIGHOUTDOORAIRTEMPERATURE                 ', &
       'ONIFHIGHZONEAIRTEMPERATURE                    ', &
       'ONIFHIGHZONECOOLING                           ', &
       'ONIFHIGHGLARE                                 ', &
       'MEETDAYLIGHTILLUMINANCESETPOINT               ', &
       'ONNIGHTIFLOWOUTDOORTEMPANDOFFDAY              ', &
       'ONNIGHTIFLOWINSIDETEMPANDOFFDAY               ', &
       'ONNIGHTIFHEATINGANDOFFDAY                     ', &
       'ONNIGHTIFLOWOUTDOORTEMPANDONDAYIFCOOLING      ', &
       'ONNIGHTIFHEATINGANDONDAYIFCOOLING             ', &
       'OFFNIGHTANDONDAYIFCOOLINGANDHIGHSOLARONWINDOW ', &
       'ONNIGHTANDONDAYIFCOOLINGANDHIGHSOLARONWINDOW  ', &
       'ONIFHIGHOUTDOORAIRTEMPANDHIGHSOLARONWINDOW    ', &
       'ONIFHIGHOUTDOORAIRTEMPANDHIGHHORIZONTALSOLAR  ', &
       'ONIFHIGHZONEAIRTEMPANDHIGHSOLARONWINDOW       ', &
       'ONIFHIGHZONEAIRTEMPANDHIGHHORIZONTALSOLAR     '/)

  INTEGER, PARAMETER, DIMENSION(NumValidWindowShadingControlTypes) :: ValidWindowShadingControlTypes=(/  &
       WSCT_ALWAYSON                      , & ! 'ALWAYSON                                    ', &
       WSCT_ALWAYSOFF                     , & ! 'ALWAYSOFF                                   ', &
       WSCT_ONIFSCHEDULED                 , & ! 'ONIFSCHEDULEALLOWS                          ', &
       WSCT_HISOLAR                       , & ! 'ONIFHIGHSOLARONWINDOW                       ', &
       WSCT_HIHORZSOLAR                   , & ! 'ONIFHIGHHORIZONTALSOLAR                     ', &
       WSCT_HIOUTAIRTEMP                  , & ! 'ONIFHIGHOUTDOORAIRTEMPERATURE                      ', &
       WSCT_HIZONEAIRTEMP                 , & ! 'ONIFHIGHZONEAIRTEMPERATURE                         ', &
       WSCT_HIZONECOOLING                 , & ! 'ONIFHIGHZONECOOLING                         ', &
       WSCT_HIGLARE                       , & ! 'ONIFHIGHGLARE                               ', &
       WSCT_MEETDAYLILUMSETP              , & ! 'MEETDAYLIGHTILLUMINANCESETPOINT             ', &
       WSCT_ONNIGHTLOOUTTEMP_OFFDAY       , & ! 'ONNIGHTIFLOWOUTDOORTEMPANDOFFDAY              ', &
       WSCT_ONNIGHTLOINTEMP_OFFDAY        , & ! 'ONNIGHTIFLOWINSIDETEMPANDOFFDAY               ', &
       WSCT_ONNIGHTIFHEATING_OFFDAY       , & ! 'ONNIGHTIFHEATINGANDOFFDAY                     ', &
       WSCT_ONNIGHTLOOUTTEMP_ONDAYCOOLING , & ! 'ONNIGHTIFLOWOUTDOORTEMPANDONDAYIFCOOLING      ', &
       WSCT_ONNIGHTIFHEATING_ONDAYCOOLING , & ! 'ONNIGHTIFHEATINGANDONDAYIFCOOLING             ', &
       WSCT_OFFNIGHT_ONDAY_HISOLARWINDOW  , & ! 'OFFNIGHTANDONDAYIFCOOLINGANDHIGHSOLARONWINDOW ', &
       WSCT_ONNIGHT_ONDAY_HISOLARWINDOW   , & ! 'ONNIGHTANDONDAYIFCOOLINGANDHIGHSOLARONWINDOW  ', &
       WSCT_ONHIOUTTEMP_HISOLARWINDOW     , & ! 'ONIFHIGHOUTDOORAIRTEMPANDHIGHSOLARONWINDOW  ', &
       WSCT_ONHIOUTTEMP_HIHORZSOLAR       , & ! 'ONIFHIGHOUTDOORAIRTEMPANDHIGHHORIZONTALSOLAR', &
       WSCT_ONHIZONETEMP_HISOLARWINDOW    , & ! 'ONIFHIGHZONEAIRTEMPANDHIGHSOLARONWINDOW     ', &
       WSCT_ONHIZONETEMP_HIHORZSOLAR      /) !  'ONIFHIGHZONEAIRTEMPANDHIGHHORIZONTALSOLAR   '/)


          ! INTERFACE BLOCK SPECIFICATIONS:na
          ! DERIVED TYPE DEFINITIONS:na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:

  INTEGER :: IOStat            ! IO Status when calling get input subroutine
  INTEGER :: ControlNumAlpha   ! Number of control alpha names being passed
  INTEGER :: ControlNumProp    ! Number of control properties being passed
  INTEGER :: ControlNum        ! DO loop counter/index for window shading control number
  INTEGER :: IShadedConst      ! Construction number of shaded construction
  INTEGER :: IShadingDevice    ! Material number of shading device
  INTEGER :: NLayers           ! Layers in shaded construction
  LOGICAL :: ErrorInName
  LOGICAL :: IsBlank
  INTEGER :: Loop
  INTEGER :: ShTyp       ! Shading type
  CHARACTER(MaxNameLength) :: ControlType ! Shading control type
  LOGICAL :: BGShadeBlindError  ! True if problem with construction that is supposed to have between-glass
                                ! shade or blind
  INTEGER :: Found

          ! FLOW:
! Get the total number of window shading control blocks
  cCurrentModuleObject='WindowProperty:ShadingControl'
  TotWinShadingControl = GetNumObjectsFound(cCurrentModuleObject)
  IF(TotWinShadingControl.EQ.0) RETURN

  ALLOCATE (WindowShadingControl(TotWinShadingControl))

  ControlNum=0
  DO Loop = 1, TotWinShadingControl

    CALL GetObjectItem(cCurrentModuleObject,Loop,cAlphaArgs,ControlNumAlpha, &
                       rNumericArgs,ControlNumProp,IOSTAT,  &
                   AlphaBlank=lAlphaFieldBlanks,NumBlank=lNumericFieldBlanks,  &
                   AlphaFieldnames=cAlphaFieldNames,NumericFieldNames=cNumericFieldNames)

    ErrorInName=.false.
    IsBlank=.false.
    CALL VerifyName(cAlphaArgs(1),WindowShadingControl%Name,ControlNum,ErrorInName,IsBlank,TRIM(cCurrentModuleObject)//' Name')
    IF (ErrorInName) THEN
      ErrorsFound=.true.
      CYCLE
    ENDIF

    ControlNum=ControlNum+1
    WindowShadingControl(ControlNum)%Name = cAlphaArgs(1)  ! Set the Control Name in the Derived Type
    WindowShadingControl(ControlNum)%ShadedConstruction = FindIteminList(cAlphaArgs(3),Construct%Name,TotConstructs)
    WindowShadingControl(ControlNum)%ShadingDevice = FindIteminList(cAlphaArgs(8),Material%Name,TotMaterials)
    WindowShadingControl(ControlNum)%Schedule = GetScheduleIndex(cAlphaArgs(5))
    WindowShadingControl(ControlNum)%SetPoint  = rNumericArgs(1)
    WindowShadingControl(ControlNum)%SetPoint2 = rNumericArgs(2)
    WindowShadingControl(ControlNum)%ShadingControlIsScheduled = .FALSE.
    IF(cAlphaArgs(6) == 'YES') WindowShadingControl(ControlNum)%ShadingControlIsScheduled = .TRUE.
    WindowShadingControl(ControlNum)%GlareControlIsActive = .FALSE.
    IF(cAlphaArgs(7) == 'YES') WindowShadingControl(ControlNum)%GlareControlIsActive = .TRUE.
    WindowShadingControl(ControlNum)%SlatAngleSchedule = GetScheduleIndex(cAlphaArgs(10))

    ControlType = cAlphaArgs(4)

    IF(ControlType=='SCHEDULE') THEN
      ControlType = 'ONIFSCHEDULEALLOWS'
      WindowShadingControl(ControlNum)%ShadingControlIsScheduled = .TRUE.
      WindowShadingControl(ControlNum)%GlareControlIsActive = .FALSE.
      CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
             '" is using obsolete '//TRIM(cAlphaFieldNames(4))//'="'//TRIM(cAlphaArgs(4))// &
             '", changing to "'//TRIM(ControlType)//'"')
      ! Error if schedule has not been specified
      IF(WindowShadingControl(ControlNum)%Schedule <= 0) THEN
        ErrorsFound = .TRUE.
        CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
              ' has '//TRIM(cAlphaFieldNames(4))//' "'//TRIM(ControlType)// &
              '" but a schedule has not been specified.')
      END IF
    END IF

    IF(ControlType(1:11)=='SCHEDULEAND') THEN
      ControlType = 'ONIFHIGH'//ControlType(12:)
      WindowShadingControl(ControlNum)%ShadingControlIsScheduled = .TRUE.
      WindowShadingControl(ControlNum)%GlareControlIsActive = .FALSE.
      CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
             '" is using obsolete '//TRIM(cAlphaFieldNames(4))//'="'//TRIM(cAlphaArgs(4))// &
             '", changing to "'//TRIM(ControlType)//'"')
      ! Error if schedule has not been specified
      IF(WindowShadingControl(ControlNum)%Schedule <= 0) THEN
        ErrorsFound = .TRUE.
        CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
              ' has '//TRIM(cAlphaFieldNames(4))//' "'//TRIM(ControlType)// &
              '" but a schedule has not been specified.')
      END IF
    END IF

    IF(ControlType(1:7)=='GLAREOR') THEN
      ControlType = 'ONIFHIGH'//ControlType(8:)
      WindowShadingControl(ControlNum)%ShadingControlIsScheduled = .FALSE.
      WindowShadingControl(ControlNum)%GlareControlIsActive = .TRUE.
      CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
             '" is using obsolete '//TRIM(cAlphaFieldNames(4))//'="'//TRIM(cAlphaArgs(4))// &
             '", changing to "'//TRIM(ControlType)//'"')
    END IF

    IF(ControlType=='GLARE') THEN
      ControlType = 'ONIFHIGHGLARE'
      WindowShadingControl(ControlNum)%ShadingControlIsScheduled = .FALSE.
      WindowShadingControl(ControlNum)%GlareControlIsActive = .TRUE.
      CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
             '" is using obsolete '//TRIM(cAlphaFieldNames(4))//'="'//TRIM(cAlphaArgs(4))// &
             '", changing to "'//TRIM(ControlType)//'"')
    END IF

    IF(WindowShadingControl(ControlNum)%ShadingDevice .GT. 0)THEN
      IF(Material(WindowShadingControl(ControlNum)%ShadingDevice)%Group == Screen .AND. .NOT. &
         (ControlType == 'ALWAYSON' .OR. ControlType == 'ALWAYSOFF' .OR. &
          ControlType == 'ONIFSCHEDULEALLOWS'))THEN
        ErrorsFound = .TRUE.
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
             '" invalid '//TRIM(cAlphaFieldNames(4))//'="'//TRIM(cAlphaArgs(4))// &
             '" for exterior screens.')
        CALL ShowContinueError('Valid shading control types for exterior window screens'// &
             ' are ALWAYSON, ALWAYSOFF, or ONIFSCHEDULEALLOWS.')
      END IF
    ELSE
      IF (WindowShadingControl(ControlNum)%ShadedConstruction > 0) THEN
        Construct(WindowShadingControl(ControlNum)%ShadedConstruction)%IsUsed=.true.
        IF(Material(Construct(WindowShadingControl(ControlNum)%ShadedConstruction)%LayerPoint(1))%Group == Screen .AND. .NOT. &
           (ControlType == 'ALWAYSON' .OR. ControlType == 'ALWAYSOFF' .OR. &
            ControlType == 'ONIFSCHEDULEALLOWS'))THEN
          ErrorsFound = .TRUE.
          CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
               '" invalid '//TRIM(cAlphaFieldNames(4))//'="'//TRIM(cAlphaArgs(4))// &
               '" for exterior screens.')
          CALL ShowContinueError('Valid shading control types for exterior window screens'// &
               ' are ALWAYSON, ALWAYSOFF, or ONIFSCHEDULEALLOWS.')
        END IF
      ELSEIF (lAlphaFieldBlanks(3)) THEN
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
           '", '//trim(cAlphaFieldNames(3))//' is blank.')
        CALL ShowContinueError('A valid construction is required.')
        ErrorsFound=.true.
      ELSE
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
           '", '//trim(cAlphaFieldNames(3))//' is invalid.')
        CALL ShowContinueError('Construction="'//trim(cAlphaArgs(3))//'" was used. A valid construction is required.')
        ErrorsFound=.true.
      ENDIF
    END IF

    ! Warning if setpoint is unintentionally zero
    IF(WindowShadingControl(ControlNum)%SetPoint == 0 .AND. &
      ControlType /= 'ALWAYSON' .AND. &
      ControlType /= 'ALWAYSOFF' .AND. &
      ControlType /= 'ONIFSCHEDULEALLOWS' .AND. ControlType /= 'SCHEDULE' .AND. &
      ControlType /= 'ONIFHIGHGLARE' .AND. ControlType /= 'GLARE' .AND. &
      ControlType /= 'DAYLIGHTILLUMINANCE' ) THEN
      CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
             '", The first SetPoint is zero.')
      CALL ShowContinueError('..You may have forgotten to specify that setpoint.')
    END IF

    ! Upward compatibility for old Shading Control Type names
    IF(ControlType=='SOLARONWINDOW' .OR. ControlType=='HORIZONTALSOLAR' .OR. ControlType=='OUTSIDEAIRTEMP' .OR. &
       ControlType=='ZONEAIRTEMP' .OR. ControlType=='ZONECOOLING') THEN
       ControlType = 'ONIFHIGH'//TRIM(ControlType)
       WindowShadingControl(ControlNum)%ShadingControlIsScheduled = .FALSE.
       WindowShadingControl(ControlNum)%GlareControlIsActive = .FALSE.
       CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
             '" is using obsolete '//TRIM(cAlphaFieldNames(4))//'="'//TRIM(cAlphaArgs(4))// &
             '", changing to "'//TRIM(ControlType)//'"')
    END IF

    ! Error if illegal control type
    Found=FindItemInList(ControlType,cValidWindowShadingControlTypes,NumValidWindowShadingControlTypes)
    IF (Found == 0) THEN
      ErrorsFound = .TRUE.
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
             '" invalid '//TRIM(cAlphaFieldNames(4))//'="'//TRIM(cAlphaArgs(4))//'".')
    ELSE
     WindowShadingControl(ControlNum)%ShadingControlType = ValidWindowShadingControlTypes(Found)
    END IF


    ! Error checks
    IF(cAlphaArgs(6) /= 'YES' .AND. cAlphaArgs(6) /= 'NO') THEN
      ErrorsFound = .true.
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
             '" invalid '//TRIM(cAlphaFieldNames(6))//'="'//TRIM(cAlphaArgs(6))//'".')
    END IF
    IF(cAlphaArgs(7) /= 'YES' .AND. cAlphaArgs(7) /= 'NO') THEN
      ErrorsFound = .true.
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
             '" invalid '//TRIM(cAlphaFieldNames(7))//'="'//TRIM(cAlphaArgs(7))//'".')
    END IF

    IF ((WindowShadingControl(ControlNum)%ShadingControlType == WSCT_ONIFSCHEDULED) .and. &
        (.NOT. WindowShadingControl(ControlNum)%ShadingControlIsScheduled)) THEN ! CR 7709 BG
      ErrorsFound = .TRUE.
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//' = "'//TRIM(WindowShadingControl(ControlNum)%Name)//'" invalid, '// &
           TRIM(cAlphaFieldNames(6))//' must be set to "Yes" for '//TRIM(cAlphaFieldNames(4))//' = OnIfScheduleAllows')
    ENDIF

    IF(cAlphaArgs(9) /= 'FIXEDSLATANGLE' .AND. cAlphaArgs(9) /= 'SCHEDULEDSLATANGLE' .AND. &
       cAlphaArgs(9) /= 'BLOCKBEAMSOLAR') THEN
      ErrorsFound = .true.
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
             '" invalid '//TRIM(cAlphaFieldNames(9))//'="'//TRIM(cAlphaArgs(9))//'".')
    ELSEIF (cAlphaArgs(9) == 'FIXEDSLATANGLE') THEN
      WindowShadingControl(ControlNum)%SlatAngleControlForBlinds = WSC_SAC_FixedSlatAngle
    ELSEIF (cAlphaArgs(9) == 'SCHEDULEDSLATANGLE') THEN
      WindowShadingControl(ControlNum)%SlatAngleControlForBlinds = WSC_SAC_ScheduledSlatAngle
    ELSEIF (cAlphaArgs(9) == 'BLOCKBEAMSOLAR') THEN
      WindowShadingControl(ControlNum)%SlatAngleControlForBlinds = WSC_SAC_BlockBeamSolar
    END IF

    ! For upward compatibility change old "noninsulating" and "insulating" shade types to
    ! INTERIORSHADE or EXTERIORSHADE
    IF(cAlphaArgs(2) == 'INTERIORNONINSULATINGSHADE' .OR.   &
       cAlphaArgs(2) == 'INTERIORINSULATINGSHADE') THEN
       CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
             '" is using obsolete '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))// &
             '", changing to "InteriorShade"')
       WindowShadingControl(ControlNum)%ShadingType = WSC_ST_InteriorShade
       cAlphaArgs(2)='INTERIORSHADE'
    ENDIF
    IF(cAlphaArgs(2) == 'EXTERIORNONINSULATINGSHADE' .OR.   &
       cAlphaArgs(2) == 'EXTERIORINSULATINGSHADE') THEN
       CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
             '" is using obsolete '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))// &
             '", changing to "ExteriorShade"')
       WindowShadingControl(ControlNum)%ShadingType = WSC_ST_ExteriorShade
       cAlphaArgs(2)='EXTERIORSHADE'
    ENDIF

    IF (ControlType == 'MEETDAYLIGHTILLUMINANCESETPOINT' .and.  &
        cAlphaArgs(2) /= 'SWITCHABLEGLAZING') THEN
      ErrorsFound = .true.
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
             '" invalid '//TRIM(cAlphaFieldNames(4))//'="'//TRIM(cAlphaArgs(4))//'".')
      CALL ShowContinueError('...'//trim(cAlphaFieldNames(2))//' must be SwitchableGlazing for this control, but'//  &
                ' entered type="'//trim(cAlphaArgs(2))//'".')
    ENDIF

    ! Check for illegal shading type name
    Found=FindItemInList(cAlphaArgs(2),cValidShadingTypes,NumValidShadingTypes)
    IF (Found == 0) THEN
      ErrorsFound = .true.
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
             '" invalid '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))//'".')
    ELSE
      WindowShadingControl(ControlNum)%ShadingType=ValidShadingTypes(Found)
    END IF

    ShTyp = WindowShadingControl(ControlNum)%ShadingType
    IShadedConst   = WindowShadingControl(ControlNum)%ShadedConstruction
    IShadingDevice = WindowShadingControl(ControlNum)%ShadingDevice


    IF(IShadedConst==0 .AND. IShadingDevice == 0) THEN
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
          '" has no matching shaded construction or shading device.')
      ErrorsFound=.true.
    ELSE IF(IShadedConst == 0 .AND. IShadingDevice > 0) THEN
      IF(ShTyp == WSC_ST_SwitchableGlazing) THEN
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
          '" has '//TRIM(cAlphaArgs(2))//'= SwitchableGlazing but no matching shaded construction')
        ErrorsFound = .true.
      END IF
      IF((ShTyp==WSC_ST_InteriorShade.OR. ShTyp==WSC_ST_ExteriorShade).AND. Material(IShadingDevice)%Group /= Shade) THEN
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
          '" has '//TRIM(cAlphaArgs(2))//'= InteriorShade or ExteriorShade but matching shading device is not a window shade')
        CALL ShowContinueError(TRIM(cAlphaFieldNames(8))//' in error="'//TRIM(Material(IShadingDevice)%Name)//'".')
        ErrorsFound = .true.
      END IF
      IF((ShTyp==WSC_ST_ExteriorScreen).AND. Material(IShadingDevice)%Group /= Screen) THEN
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
          '" has '//TRIM(cAlphaArgs(2))//'= ExteriorScreen but matching shading device is not a window screen')
        CALL ShowContinueError(TRIM(cAlphaFieldNames(8))//' in error="'//TRIM(Material(IShadingDevice)%Name)//'".')
        ErrorsFound = .true.
      END IF
      IF((ShTyp==WSC_ST_InteriorBlind.OR. ShTyp==WSC_ST_ExteriorBlind).AND. Material(IShadingDevice)%Group /= WindowBlind) THEN
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
          '" has '//TRIM(cAlphaArgs(2))//'= InteriorBlind or ExteriorBlind but matching shading device is not a window blind')
        CALL ShowContinueError(TRIM(cAlphaFieldNames(8))//' in error="'//TRIM(Material(IShadingDevice)%Name)//'".')
        ErrorsFound = .true.
      END IF
      IF(ShTyp==WSC_ST_BetweenGlassBlind.OR. ShTyp==WSC_ST_BetweenGlassBlind) THEN
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
        '" has '//TRIM(cAlphaArgs(2))//'= BetweenGlassShade or BetweenGlassBlind and')
        CALL ShowContinueError(TRIM(cAlphaFieldNames(8))//' is specified. This is illegal. Specify shaded construction instead.')
        ErrorsFound = .true.
      END IF
    ELSE IF(IShadedConst > 0 .AND. IShadingDevice > 0) THEN
      IShadingDevice = 0
      CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
                  '" Both '//TRIM(cAlphaFieldNames(3))//' and '//TRIM(cAlphaFieldNames(8))//' are specified.')
      CALL ShowContinueError('The '//TRIM(cAlphaFieldNames(3))//'="'//TRIM(Construct(IShadedConst)%Name)//'" will be used.')
    END IF

    ! If type = interior or exterior shade or blind require that the shaded construction
    ! have a shade layer in the correct position
    IF(IShadedConst /= 0) THEN

      NLayers = Construct(IShadedConst)%TotLayers
      BGShadeBlindError = .FALSE.
      IShadingDevice=0
      IF (Construct(IShadedConst)%LayerPoint(NLayers) /= 0) THEN
        IF(WindowShadingControl(ControlNum)%ShadingType == WSC_ST_InteriorShade) THEN
          IShadingDevice=Construct(IShadedConst)%LayerPoint(NLayers)
          IF(Material(Construct(IShadedConst)%LayerPoint(NLayers))%Group /= Shade) THEN
            ErrorsFound = .TRUE.
            CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
              '" the '//TRIM(cAlphaFieldNames(3))//'="'//TRIM(cAlphaArgs(3))//'"')
            CALL ShowContinueError('of '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))//  &
               '" should have a shade layer on the inside of the window.')
          END IF
        ELSE IF(WindowShadingControl(ControlNum)%ShadingType == WSC_ST_ExteriorShade) THEN
          IShadingDevice=Construct(IShadedConst)%LayerPoint(1)
          IF(Material(Construct(IShadedConst)%LayerPoint(1))%Group /= Shade) THEN
            ErrorsFound = .TRUE.
            CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
              '" the '//TRIM(cAlphaFieldNames(3))//'="'//TRIM(cAlphaArgs(3))//'"')
            CALL ShowContinueError('of '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))//  &
               '" should have a shade layer on the outside of the window.')
          END IF
        ELSE IF(WindowShadingControl(ControlNum)%ShadingType == WSC_ST_ExteriorScreen) THEN
          IShadingDevice=Construct(IShadedConst)%LayerPoint(1)
          IF(Material(Construct(IShadedConst)%LayerPoint(1))%Group /= Screen) THEN
            ErrorsFound = .TRUE.
            CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
              '" the '//TRIM(cAlphaFieldNames(3))//'="'//TRIM(cAlphaArgs(3))//'"')
            CALL ShowContinueError('of '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))//  &
               '" should have a screen layer on the outside of the window.')
          END IF
        ELSE IF(WindowShadingControl(ControlNum)%ShadingType == WSC_ST_InteriorBlind) THEN
          IShadingDevice=Construct(IShadedConst)%LayerPoint(NLayers)
          IF(Material(Construct(IShadedConst)%LayerPoint(NLayers))%Group /= WindowBlind) THEN
            ErrorsFound = .TRUE.
            CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
              '" the '//TRIM(cAlphaFieldNames(3))//'="'//TRIM(cAlphaArgs(3))//'"')
            CALL ShowContinueError('of '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))//  &
               '" should have a blind layer on the inside of the window.')
          END IF
        ELSE IF(WindowShadingControl(ControlNum)%ShadingType == WSC_ST_ExteriorBlind) THEN
          IShadingDevice=Construct(IShadedConst)%LayerPoint(1)
          IF(Material(Construct(IShadedConst)%LayerPoint(1))%Group /= WindowBlind) THEN
            ErrorsFound = .TRUE.
            CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
              '" the '//TRIM(cAlphaFieldNames(3))//'="'//TRIM(cAlphaArgs(3))//'"')
            CALL ShowContinueError('of '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))//  &
               '" should have a blind layer on the outside of the window.')
          END IF
        ELSE IF(WindowShadingControl(ControlNum)%ShadingType == WSC_ST_BetweenGlassShade) THEN
          IF(NLayers /= 5 .AND. NLayers /= 7) BGShadeBlindError = .TRUE.
          IF(NLayers==5) THEN
            IF(Material(Construct(IShadedConst)%LayerPoint(3))%Group /= Shade) BGShadeBlindError = .TRUE.
          END IF
          IF(NLayers==7) THEN
            IF(Material(Construct(IShadedConst)%LayerPoint(5))%Group /= Shade) BGShadeBlindError = .TRUE.
          END IF
          IF(BGShadeBlindError) THEN
            ErrorsFound = .TRUE.
            CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
              '" the '//TRIM(cAlphaFieldNames(3))//'="'//TRIM(cAlphaArgs(3))//'"')
            CALL ShowContinueError('of '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))//  &
               '" should have two or three glass layers and a')
            CALL ShowContinueError('between-glass shade layer with a gas layer on each side.')
          END IF
        ELSE IF(WindowShadingControl(ControlNum)%ShadingType == WSC_ST_BetweenGlassBlind) THEN
          IF(NLayers /= 5 .AND. NLayers /= 7) BGShadeBlindError = .TRUE.
          IF(NLayers==5) THEN
            IF(Material(Construct(IShadedConst)%LayerPoint(3))%Group /= WindowBlind) BGShadeBlindError = .TRUE.
          END IF
          IF(NLayers==7) THEN
            IF(Material(Construct(IShadedConst)%LayerPoint(5))%Group /= WindowBlind) BGShadeBlindError = .TRUE.
          END IF
          IF(BGShadeBlindError) THEN
            ErrorsFound = .TRUE.
            CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
              '" the '//TRIM(cAlphaFieldNames(3))//'="'//TRIM(cAlphaArgs(3))//'"')
            CALL ShowContinueError('of '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))//  &
               '" should have two or three glass layers and a')
            CALL ShowContinueError('between-glass blind layer with a gas layer on each side.')
          END IF
        END IF
      ENDIF
      IF(IShadingDevice > 0) THEN
        IF((ShTyp==WSC_ST_InteriorShade.OR. ShTyp==WSC_ST_ExteriorShade).AND. Material(IShadingDevice)%Group /= Shade) THEN
          CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
            '" has '//TRIM(cAlphaFieldNames(2))//'= InteriorShade or ExteriorShade '//  &
            'but matching shading device is not a window shade')
          CALL ShowContinueError('Shading Device in error="'//TRIM(Material(IShadingDevice)%Name)//'".')
          ErrorsFound = .true.
        END IF
        IF((ShTyp==WSC_ST_ExteriorScreen).AND. Material(IShadingDevice)%Group /= Screen) THEN
          CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
            '" has '//TRIM(cAlphaFieldNames(2))//'= ExteriorScreen '//  &
            'but matching shading device is not an exterior window screen.')
          CALL ShowContinueError('Shading Device in error="'//TRIM(Material(IShadingDevice)%Name)//'".')
          ErrorsFound = .true.
        END IF
        IF((ShTyp==WSC_ST_InteriorBlind.OR. ShTyp==WSC_ST_ExteriorBlind).AND. Material(IShadingDevice)%Group /= WindowBlind) THEN
          CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(WindowShadingControl(ControlNum)%Name)//  &
            '" has '//TRIM(cAlphaFieldNames(2))//'= InteriorBlind or ExteriorBlind '//  &
            'but matching shading device is not a window blind.')
          CALL ShowContinueError('Shading Device in error="'//TRIM(Material(IShadingDevice)%Name)//'".')
          ErrorsFound = .true.
        END IF
      END IF

    END IF

  END DO  ! End of loop over window shading controls

RETURN

END SUBROUTINE GetWindowShadingControlData

SUBROUTINE GetStormWindowData(ErrorsFound)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Fred Winkelmann
          !       DATE WRITTEN   December 2003
          !       MODIFIED       na

          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! Reads in the storm window data from the input file,
          ! interprets it and puts it in the derived type

          ! METHODOLOGY EMPLOYED:

          ! REFERENCES:

          ! USE STATEMENTS:
  USE DataIPShortCuts
  USE InputProcessor, ONLY: GetNumObjectsFound, GetObjectItem, FindItemInList, VerifyName
  USE General, ONLY: JulianDay,TrimSigDigits

  IMPLICIT NONE    ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
  LOGICAL, INTENT(INOUT) :: ErrorsFound ! If errors found in input

          ! SUBROUTINE PARAMETER DEFINITIONS:na
          ! INTERFACE BLOCK SPECIFICATIONS:na
          ! DERIVED TYPE DEFINITIONS:na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:

  INTEGER :: IOStat            ! IO Status when calling get input subroutine
  INTEGER :: StormWinNumAlpha   ! Number of alpha names being passed
  INTEGER :: StormWinNumProp    ! Number of properties being passed
  INTEGER :: StormWinNum        ! Index for storm window number
  INTEGER :: loop               ! Do loop counter
  INTEGER :: SurfNum            ! Surface number
  INTEGER :: MatNum             ! Material number

          ! FLOW:

  ! Get the total number of storm window input objects
  cCurrentModuleObject='WindowProperty:StormWindow'
  TotStormWin = GetNumObjectsFound(cCurrentModuleObject)
  IF(TotStormWin == 0) RETURN

  ALLOCATE (StormWindow(TotStormWin))

  StormWinNum = 0
  DO loop = 1,TotStormWin

    CALL GetObjectItem(cCurrentModuleObject,loop,cAlphaArgs,StormWinNumAlpha, &
                       rNumericArgs,StormWinNumProp,IOSTAT,  &
                   AlphaBlank=lAlphaFieldBlanks,NumBlank=lNumericFieldBlanks,  &
                   AlphaFieldnames=cAlphaFieldNames,NumericFieldNames=cNumericFieldNames)
    StormWinNum=StormWinNum+1
    StormWindow(StormWinNum)%BaseWindowNum = FindIteminList(cAlphaArgs(1),Surface%Name,TotSurfaces)
    StormWindow(StormWinNum)%StormWinMaterialNum = FindIteminList(cAlphaArgs(2),Material%Name,TotMaterials)
    StormWindow(StormWinNum)%StormWinDistance = rNumericArgs(1)
    StormWindow(StormWinNum)%MonthOn = rNumericArgs(2)
    StormWindow(StormWinNum)%DayOfMonthOn = rNumericArgs(3)
    StormWindow(StormWinNum)%DateOn=JulianDay(StormWindow(StormWinNum)%MonthOn,StormWindow(StormWinNum)%DayOfMonthOn,1)
    StormWindow(StormWinNum)%MonthOff = rNumericArgs(4)
    StormWindow(StormWinNum)%DayOfMonthOff = rNumericArgs(5)
    StormWindow(StormWinNum)%DateOff=JulianDay(StormWindow(StormWinNum)%MonthOff,StormWindow(StormWinNum)%DayOfMonthOff,1)

    IF (StormWindow(StormWinNum)%DateOn == StormWindow(StormWinNum)%DateOff) THEN
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//': Date On = Date Off -- not allowed,'//  &
                           ' occured in WindowProperty:StormWindow Input #'//TRIM(TrimSigDigits(StormWinNum)))
      ErrorsFound=.true.
    ENDIF

    SELECT CASE (StormWindow(StormWinNum)%MonthOn)

     CASE (1,3,5,7,8,10,12)
       IF (StormWindow(StormWinNum)%DayOfMonthOn > 31) THEN
         CALL ShowSevereError(TRIM(cCurrentModuleObject)//': Date On (Day of Month) ['//  &
                                 TRIM(TrimSigDigits(StormWindow(StormWinNum)%DayOfMonthOn))//'],'//  &
                                 ' invalid for WindowProperty:StormWindow Input #'//TRIM(TrimSigDigits(StormWinNum)))
         ErrorsFound=.true.
       ENDIF
     CASE (4,6,9,11)
       IF (StormWindow(StormWinNum)%DayOfMonthOn > 30) THEN
         CALL ShowSevereError(TRIM(cCurrentModuleObject)//': Date On (Day of Month) ['//  &
                                 TRIM(TrimSigDigits(StormWindow(StormWinNum)%DayOfMonthOn))//'],'//  &
                                 ' invalid for WindowProperty:StormWindow Input #'//TRIM(TrimSigDigits(StormWinNum)))
         ErrorsFound=.true.
       ENDIF
     CASE (2)
       IF (StormWindow(StormWinNum)%DayOfMonthOn > 29) THEN
         CALL ShowSevereError(TRIM(cCurrentModuleObject)//': Date On (Day of Month) ['//  &
                                 TRIM(TrimSigDigits(StormWindow(StormWinNum)%DayOfMonthOn))//'],'//  &
                                 ' invalid for WindowProperty:StormWindow Input #'//TRIM(TrimSigDigits(StormWinNum)))
         ErrorsFound=.true.
       ENDIF
     CASE DEFAULT
       CALL ShowSevereError(TRIM(cCurrentModuleObject)//': Date On Month ['//  &
                               TRIM(TrimSigDigits(StormWindow(StormWinNum)%MonthOn))//'],'//  &
                               ' invalid for WindowProperty:StormWindow Input #'//TRIM(TrimSigDigits(StormWinNum)))
       ErrorsFound=.true.
    END SELECT
    SELECT CASE (StormWindow(StormWinNum)%MonthOff)

     CASE (1,3,5,7,8,10,12)
       IF (StormWindow(StormWinNum)%DayOfMonthOff > 31) THEN
         CALL ShowSevereError(TRIM(cCurrentModuleObject)//': Date Off (Day of Month) ['//  &
                                 TRIM(TrimSigDigits(StormWindow(StormWinNum)%DayOfMonthOff))//'],'//  &
                                 ' invalid for WindowProperty:StormWindow Input #'//TRIM(TrimSigDigits(StormWinNum)))
         ErrorsFound=.true.
       ENDIF
     CASE (4,6,9,11)
       IF (StormWindow(StormWinNum)%DayOfMonthOff > 30) THEN
         CALL ShowSevereError(TRIM(cCurrentModuleObject)//': Date Off (Day of Month) ['//  &
                                 TRIM(TrimSigDigits(StormWindow(StormWinNum)%DayOfMonthOff))//'],'//  &
                                 ' invalid for WindowProperty:StormWindow Input #'//TRIM(TrimSigDigits(StormWinNum)))
         ErrorsFound=.true.
       ENDIF
     CASE (2)
       IF (StormWindow(StormWinNum)%DayOfMonthOff > 29) THEN
         CALL ShowSevereError(TRIM(cCurrentModuleObject)//': Date Off (Day of Month) ['//  &
                                 TRIM(TrimSigDigits(StormWindow(StormWinNum)%DayOfMonthOff))//'],'//  &
                                 ' invalid for WindowProperty:StormWindow Input #'//TRIM(TrimSigDigits(StormWinNum)))
         ErrorsFound=.true.
       ENDIF
     CASE DEFAULT
       CALL ShowSevereError(TRIM(cCurrentModuleObject)//': Date Off Month ['//  &
                               TRIM(TrimSigDigits(StormWindow(StormWinNum)%MonthOff))//'],'//  &
                               ' invalid for WindowProperty:StormWindow Input #'//TRIM(TrimSigDigits(StormWinNum)))
       ErrorsFound=.true.
    END SELECT
  END DO

  ! Error checks

  DO StormWinNum = 1,TotStormWin
    ! Require BaseWindowNum be that of an exterior window
    SurfNum = StormWindow(StormWinNum)%BaseWindowNum
    IF(SurfNum == 0) THEN
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(cAlphaArgs(1))//  &
         '" invalid.')
      ErrorsFound = .true.
    ELSE
      IF(Surface(SurfNum)%Class /= SurfaceClass_Window .OR. Surface(SurfNum)%ExtBoundCond /= 0) THEN
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(cAlphaArgs(1))//'"')
        CALL ShowSevereError('cannot be used with surface='//TRIM(Surface(SurfNum)%Name))
        CALL ShowContinueError('because that surface is not an exterior window.')
        ErrorsFound = .true.
      END IF
    END IF

    ! Require that storm window material be glass
    MatNum = StormWindow(StormWinNum)%StormWinMaterialNum
    IF(SurfNum > 0) THEN
      IF(MatNum == 0) THEN
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(cAlphaArgs(1))//'"')
        CALL ShowContinueError(TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))//  &
            '" not found as storm window layer.')
        ErrorsFound = .true.
      ELSE
        IF(Material(MatNum)%Group /= WindowGlass) THEN
          CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(cAlphaArgs(1))//'"')
          CALL ShowContinueError(TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))//  &
              'must be a WindowMaterial:Glazing or WindowMaterial:Glazing:RefractionExtinctionMethod')
          ErrorsFound = .true.
        END IF
      END IF
    END IF

    ! Error if base window has airflow control
    IF(SurfNum > 0) THEN
      IF(SurfaceWindow(SurfNum)%AirflowControlType /= 0) THEN
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(cAlphaArgs(1))//'"')
        CALL ShowContinueError(' cannot be used '//  &
          'because it is an airflow window (i.e., has WindowProperty:AirflowControl specified)')
        ErrorsFound = .true.
      END IF
    END IF

    ! Check for reversal of on and off times
    IF(SurfNum > 0) THEN
      IF((Latitude > 0.0d0  .AND. (StormWindow(StormWinNum)%MonthOn < StormWindow(StormWinNum)%MonthOff)) .OR. &
         (Latitude <= 0.0d0 .AND. (StormWindow(StormWinNum)%MonthOn > StormWindow(StormWinNum)%MonthOff))) THEN
        CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(cAlphaArgs(1))//'" check times that storm window')
        CALL ShowContinueError('is put on (month='//TRIM(TrimSigDigits(StormWindow(StormWinNum)%MonthOn))//  &
           ', day='//TRIM(TrimSigDigits(StormWindow(StormWinNum)%DayOfMonthOn))//')'// &
           ' and taken off (month='//TRIM(TrimSigDigits(StormWindow(StormWinNum)%MonthOff))//  &
           ', day='//TRIM(TrimSigDigits(StormWindow(StormWinNum)%DayOfMonthOff))//');')
        CALL ShowContinueError('these times may be reversed for your building latitude='//  &
           TRIM(TrimSigDigits(Latitude,2))//' deg.')
      END IF
    END IF
  END DO

RETURN
END SUBROUTINE GetStormWindowData

SUBROUTINE GetWindowGapAirflowControlData(ErrorsFound)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Fred Winkelmann
          !       DATE WRITTEN   Feb 2003
          !       MODIFIED       June 2003, FCW: add destination = return air;
          !                        more error messages
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! Reads in the window airflow control information from the input data file,
          ! interprets it and puts it in the SurfaceWindow derived type

          ! METHODOLOGY EMPLOYED: na
          ! REFERENCES: na

          ! USE STATEMENTS:
  USE DataIPShortCuts
  USE InputProcessor, ONLY: GetNumObjectsFound, GetObjectItem, FindItemInList, SameString
  USE ScheduleManager, ONLY: GetScheduleIndex

  IMPLICIT NONE    ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
  LOGICAL, INTENT(INOUT) :: ErrorsFound ! If errors found in input

          ! SUBROUTINE PARAMETER DEFINITIONS:na
          ! INTERFACE BLOCK SPECIFICATIONS:na
          ! DERIVED TYPE DEFINITIONS:na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:

  INTEGER :: IOStat                   ! IO Status when calling get input subroutine
  INTEGER :: ControlNumAlpha          ! Number of control alpha names being passed
  INTEGER :: ControlNumProp           ! Number of control properties being passed
  INTEGER :: TotWinAirflowControl     ! Total window airflow control statements
  LOGICAL :: WrongSurfaceType         ! True if associated surface is not 2- or 3-pane exterior window
  INTEGER :: Loop
  INTEGER :: SurfNum                  ! Surface number
  INTEGER :: ConstrNum                ! Construction number
  INTEGER :: ConstrNumSh              ! Shaded Construction number
  INTEGER :: WSCptr                   ! Window shading control pointer
  INTEGER :: MatGapFlow               ! Material number of gas in airflow gap of window's construction
  INTEGER :: MatGapFlow1,MatGapFlow2  ! Material number of gas on either side of a between-glass shade/blind
                                      ! of the shaded construction of airflow window

        ! Get the total number of window airflow control statements
  cCurrentModuleObject='WindowProperty:AirflowControl'
  TotWinAirflowControl = GetNumObjectsFound(cCurrentModuleObject)
  IF(TotWinAirflowControl.EQ.0) RETURN

  DO Loop = 1,TotWinAirflowControl   ! Loop through all surfaces in the input...

    CALL GetObjectItem(cCurrentModuleObject,Loop,cAlphaArgs,ControlNumAlpha, &
                       rNumericArgs,ControlNumProp,IOSTAT,  &
                   AlphaBlank=lAlphaFieldBlanks,NumBlank=lNumericFieldBlanks,  &
                   AlphaFieldnames=cAlphaFieldNames,NumericFieldNames=cNumericFieldNames)

    SurfNum = FindItemInList(cAlphaArgs(1),Surface%Name,TotSurfaces)
    IF(SurfNum == 0) THEN
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(cAlphaArgs(1))//'" not found.')
      ErrorsFound =.true.
    END IF
          ! Check that associated surface is a 2- or 3-pane exterior window
    WrongSurfaceType = .FALSE.
    IF(SurfNum /= 0) THEN
      IF(Surface(SurfNum)%Class /= SurfaceClass_Window) WrongSurfaceType = .TRUE.
      IF(Surface(SurfNum)%Class == SurfaceClass_Window) THEN
        ConstrNum = Surface(SurfNum)%Construction
        IF(Construct(ConstrNum)%TotGlassLayers /= 2 .AND. Construct(ConstrNum)%TotGlassLayers /= 3) &
           WrongSurfaceType = .TRUE.
        IF(Surface(SurfNum)%ExtBoundCond /= ExternalEnvironment) WrongSurfaceType = .TRUE.
      END IF
      IF(WrongSurfaceType) THEN
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(cAlphaArgs(1))//  &
          '" is not an exterior window with 2 or 3 glass layers.')
        ErrorsFound = .TRUE.
      END IF
    END IF

    ! Error if illegal airflow source
    IF(cAlphaArgs(2) /= 'INDOORAIR'.AND. cAlphaArgs(2) /= 'OUTDOORAIR') THEN
      ErrorsFound = .TRUE.
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(cAlphaArgs(1))//  &
         '" invalid '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))//'"')
    END IF

    ! Error if illegal airflow destination
    IF(cAlphaArgs(3) /= 'INDOORAIR'.AND. cAlphaArgs(3) /= 'OUTDOORAIR'.AND. &
       cAlphaArgs(3) /= 'RETURNAIR'  ) THEN
      ErrorsFound = .TRUE.
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(cAlphaArgs(1))//  &
         '" invalid '//TRIM(cAlphaFieldNames(3))//'="'//TRIM(cAlphaArgs(3))//'"')
    END IF


    ! Error if source = OutsideAir and destination = ReturnAir
    IF(cAlphaArgs(2) == 'OUTDOORAIR'.AND. cAlphaArgs(3) == 'RETURNAIR') THEN
      ErrorsFound = .TRUE.
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(cAlphaArgs(1))//  &
         '" invalid '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))//'"')
      CALL ShowContinueError('..when '//TRIM(cAlphaFieldNames(3))//'="'//TRIM(cAlphaArgs(3))//'"')
    END IF

    ! Error if illegal airflow control type
    IF(cAlphaArgs(4) /= 'ALWAYSONATMAXIMUMFLOW'.AND. cAlphaArgs(4) /= 'ALWAYSOFF'.AND. &
          cAlphaArgs(4) /= 'SCHEDULEDONLY') THEN
      ErrorsFound = .TRUE.
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(cAlphaArgs(1))//  &
         '" invalid '//TRIM(cAlphaFieldNames(4))//'="'//TRIM(cAlphaArgs(4))//'"')
    END IF

    ! Error if illegal value for Airflow Has Multiplier Schedule
    IF(cAlphaArgs(5) /= 'YES'.AND. cAlphaArgs(5) /= 'NO') THEN
      ErrorsFound = .TRUE.
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(cAlphaArgs(1))//  &
         '" invalid '//TRIM(cAlphaFieldNames(5))//'="'//TRIM(cAlphaArgs(5))//'"')
    END IF

    ! Error if Airflow Control Type = ScheduledOnly and Airflow Has Multiplier Schedule = No
    IF(cAlphaArgs(4) == 'SCHEDULEDONLY'.AND. cAlphaArgs(5) == 'NO') THEN
      ErrorsFound = .TRUE.
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(cAlphaArgs(1))//  &
         '" invalid '//TRIM(cAlphaFieldNames(4))//'="'//TRIM(cAlphaArgs(4))//'"')
      CALL ShowContinueError('..when '//TRIM(cAlphaFieldNames(5))//'="'//TRIM(cAlphaArgs(5))//'"')

    END IF

    ! Warning if Airflow Control Type = AlwaysOnAtMaxFlow and Airflow Has Multiplier Schedule = Yes
    IF(cAlphaArgs(4) == 'ALWAYSONATMAXIMUMFLOW'.AND. cAlphaArgs(5) == 'YES') THEN
      CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(cAlphaArgs(1))//  &
        'has '//TRIM(cAlphaFieldNames(4))//'="'//TRIM(cAlphaArgs(4))//'"')
      CALL ShowContinueError('..but '//TRIM(cAlphaFieldNames(5))//'="'//TRIM(cAlphaArgs(5))//  &
        'If specified, the '//TRIM(cAlphaFieldNames(5))//' will be ignored.')
    END IF

    ! Warning if Airflow Control Type = AlwaysOff and Airflow Has Multiplier Schedule = Yes
    IF(cAlphaArgs(4) == 'ALWAYSOFF'.AND. cAlphaArgs(5) == 'YES') THEN
      CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(cAlphaArgs(1))//  &
        'has '//TRIM(cAlphaFieldNames(4))//'="'//TRIM(cAlphaArgs(4))//'"')
      CALL ShowContinueError('..but '//TRIM(cAlphaFieldNames(5))//'="'//TRIM(cAlphaArgs(5))//  &
        '". If specified, the '//TRIM(cAlphaFieldNames(5))//' will be ignored.')
    END IF

    IF(SurfNum > 0) THEN
      AirflowWindows = .TRUE.
      IF (SameString(cAlphaArgs(2),'IndoorAir')) THEN
        SurfaceWindow(SurfNum)%AirflowSource = AirFlowWindow_Source_IndoorAir
      ELSEIF (SameString(cAlphaArgs(2),'OutdoorAir')) THEN
        SurfaceWindow(SurfNum)%AirflowSource = AirFlowWindow_Source_OutdoorAir
      ENDIF
      IF (SameString(cAlphaArgs(3),'IndoorAir')) THEN
        SurfaceWindow(SurfNum)%AirflowDestination = AirFlowWindow_Destination_IndoorAir
      ELSEIF (SameString(cAlphaArgs(3),'OutdoorAir')) THEN
        SurfaceWindow(SurfNum)%AirflowDestination = AirFlowWindow_Destination_OutdoorAir
      ELSEIF (SameString(cAlphaArgs(3),'ReturnAir')) THEN
        SurfaceWindow(SurfNum)%AirflowDestination = AirFlowWindow_Destination_ReturnAir
      ENDIF
      IF (SameString(cAlphaArgs(4),'AlwaysOnAtMaximumFlow'))  THEN
        SurfaceWindow(SurfNum)%AirflowControlType = AirFlowWindow_ControlType_MaxFlow
      ELSEIF (SameString(cAlphaArgs(4),'AlwaysOff'))  THEN
        SurfaceWindow(SurfNum)%AirflowControlType = AirFlowWindow_ControlType_AlwaysOff
      ELSEIF (SameString(cAlphaArgs(4),'ScheduledOnly'))  THEN
        SurfaceWindow(SurfNum)%AirflowControlType = AirFlowWindow_ControlType_Schedule
      ENDIF
      SurfaceWindow(SurfNum)%MaxAirflow = rNumericArgs(1)
      IF(cAlphaArgs(4) == 'SCHEDULEDONLY' .AND. cAlphaArgs(5) == 'YES') THEN
        IF(lAlphaFieldBlanks(6)) THEN
          ErrorsFound = .TRUE.
          CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(cAlphaArgs(1))//  &
             '", has '//TRIM(cAlphaFieldNames(4))//'="'//TRIM(cAlphaArgs(4))//'"')
          CALL ShowContinueError('..and '//TRIM(cAlphaFieldNames(5))//'="'//TRIM(cAlphaArgs(5))//  &
             '", but no '//TRIM(cAlphaFieldNames(6))//' specified.')
        ELSE
          SurfaceWindow(SurfNum)%AirflowHasSchedule = .TRUE.
          SurfaceWindow(SurfNum)%AirflowSchedulePtr = GetScheduleIndex(cAlphaArgs(6))
          IF(SurfaceWindow(SurfNum)%AirflowSchedulePtr==0) THEN
            ErrorsFound = .TRUE.
            CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(cAlphaArgs(1))//  &
              '", invalid '//TRIM(cAlphaFieldNames(6))//'="'//TRIM(cAlphaArgs(6))//'"')
          END IF
        END IF
      END IF
      ! Warning if associated window is an interior window
      IF(Surface(SurfNum)%ExtBoundCond /= ExternalEnvironment .AND. .NOT.ErrorsFound) &
        CALL ShowWarningError(TRIM(cCurrentModuleObject)//'="'//TRIM(cAlphaArgs(1))//  &
                 '", is an Interior window; cannot be an airflow window.')
      IF(.NOT.ErrorsFound) THEN
        ! Require that gas in airflow gap has type = air
        MatGapFlow = Construct(ConstrNum)%LayerPoint(2)
        IF(Construct(ConstrNum)%TotGlassLayers==3) MatGapFlow = Construct(ConstrNum)%LayerPoint(4)
        IF(Material(MatGapFlow)%GasType(1) /= 1) THEN
          ErrorsFound = .TRUE.
          CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(cAlphaArgs(1))//  &
            '", Gas type not air in airflow gap of construction '//TRIM(Construct(ConstrNum)%Name))
        END IF
        ! Require that gas be air in airflow gaps on either side of a between glass shade/blind
        WSCptr = Surface(SurfNum)%WindowShadingControlPtr
        IF(WSCptr > 0) THEN
          IF(WindowShadingControl(WSCptr)%ShadingType==WSC_ST_BetweenGlassShade .OR. &
             WindowShadingControl(WSCptr)%ShadingType==WSC_ST_BetweenGlassBlind) THEN
             ConstrNumSh = WindowShadingControl(WSCptr)%ShadedConstruction
             IF(Construct(ConstrNum)%TotGlassLayers==2) THEN
               MatGapFlow1 = Construct(ConstrNumSh)%LayerPoint(2)
               MatGapFlow2 = Construct(ConstrNumSh)%LayerPoint(4)
             ELSE
               MatGapFlow1 = Construct(ConstrNumSh)%LayerPoint(4)
               MatGapFlow2 = Construct(ConstrNumSh)%LayerPoint(6)
             END IF
             IF(Material(MatGapFlow1)%GasType(1) /= 1 .OR. Material(MatGapFlow2)%GasType(1) /= 1) THEN
               ErrorsFound = .TRUE.
               CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(cAlphaArgs(1))//  &
                   '", gas type must be air on either side of the shade/blind')
             END IF
          END IF
        END IF
      END IF
    END IF

  END DO  ! End of loop over window airflow controls

RETURN

END SUBROUTINE GetWindowGapAirflowControlData

SUBROUTINE GetOSCData(ErrorsFound)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Linda Lawrie
          !       DATE WRITTEN   May 2000
          !       MODIFIED       Jul 2011, M.J. Witte and C.O. Pedersen, add new fields to OSC for last T, max and min
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! This subroutine gets the OtherSideCoefficient data.

          ! METHODOLOGY EMPLOYED:
          ! na

          ! REFERENCES:
          ! Other Side Coefficient Definition
          ! OtherSideCoefficients,
          !       \memo This object sets the other side conditions for a surface in a variety of ways.
          !   A1, \field OtherSideCoeff Name
          !       \required-field
          !       \reference OSCNames
          !       \reference OutFaceEnvNames
          !   N1, \field Combined convective/radiative film coefficient
          !       \required-field
          !       \type real
          !       \note if>0, N1 becomes exterior convective/radiative film coefficient and other fields
          !       \note are used to calc outside air temp then exterior surface temp based on outside air
          !       \note and specified coefficient
          !       \note if<=0, then remaining fields calculate the outside surface temperature(?)
          !       \note following fields are used in the equation:
          !       \note SurfTemp=N7*TempZone + N4*OutsideDryBulb + N2*N3 + GroundTemp*N5 + WindSpeed*N6*OutsideDryBulb
          !   N2, \field User selected Constant Temperature
          !       \units C
          !       \type real
          !       \note This parameter will be overwritten by the values from the schedule(A2 below) if one is present
          !   N3, \field Coefficient modifying the user selected constant temperature
          !       \note This coefficient is used even with a schedule.  It should normally be 1.0 in that case
          !   N4, \field Coefficient modifying the external dry bulb temperature
          !       \type real
          !   N5, \field Coefficient modifying the ground temperature
          !       \type real
          !   N6, \field Coefficient modifying the wind speed term (s/m)
          !       \type real
          !   N7, \field Coefficient modifying the zone air temperature part of the equation
          !       \type real
          !   A2, \field ScheduleName for constant temperature
          !       \note Name of Schedule for values of "const" temperature.
          !       \note Schedule values replace N2 - User selected constant temperature.
          !       \type object-list
          !       \object-list ScheduleNames
          !   A3, \field Sinusoidal Variation of Constant Temperature Coefficient
          !       \note Optionally used to vary Constant Temperature Coefficient with unitary sine wave
          !       \type choice
          !       \key Yes
          !       \key No
          !       \default No
          !   N8; \field Period of Sinusoidal Variation
          !       \note Use with sinusoidal variation to define the time period
          !       \type real
          !       \units hr
          !       \default 24
          !  N9, \field Previous Other Side Temperature Coefficient
          !      \note This coeffient multiplies the other side temperature result from the
          !      \note previous zone timestep
          !      \type real
          !      \default 0
          ! N10, \field Minimum Other Side Temperature
          !      \type real
          !      \units C
          !      \default -100
          ! N11; \field Maximum Other Side Temperature
          !      \type real
          !      \units C
          !      \default 200


          ! USE STATEMENTS:
  USE DataIPShortCuts
  USE InputProcessor, ONLY: GetNumObjectsFound, GetObjectItem, FindItemInList, VerifyName, SameString
  USE ScheduleManager, ONLY: GetScheduleIndex
  USE General, ONLY: RoundSigDigits

  IMPLICIT NONE    ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
  LOGICAL, INTENT(INOUT) :: ErrorsFound

          ! SUBROUTINE PARAMETER DEFINITIONS:
  CHARACTER(len=*), PARAMETER :: OSCFormat1="('! <Other Side Coefficients>,Name,"// &
                            "Combined convective/radiative film coefficient {W/m2-K},"// &
                            "User selected Constant Temperature {C},Coefficient modifying the constant temperature term,"// &
                            "Coefficient modifying the external dry bulb temperature term,"//  &
                            "Coefficient modifying the ground temperature term,"//  &
                            "Coefficient modifying the wind speed term {s/m},"//  &
                            "Coefficient modifying the zone air temperature term,"//  &
                            "Constant Temperature Schedule Name,"//  &
                            "Sinusoidal Variation,"//  &
                            "Period of Sinusoidal Variation,"//  &
                            "Previous Other Side Temperature Coefficient,"//  &
                            "Minimum Other Side Temperature {C},"//  &
                            "Maximum Other Side Temperature {C}')"

          ! INTERFACE BLOCK SPECIFICATIONS
          ! na

          ! DERIVED TYPE DEFINITIONS
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
  INTEGER NumAlphas
  INTEGER NumProps
  INTEGER Loop
  INTEGER IOSTAT
  INTEGER OSCNum
  LOGICAL ErrorInName
  LOGICAL IsBlank
  CHARACTER(len=52) cOSCLimitsString

  cCurrentModuleObject='SurfaceProperty:OtherSideCoefficients'
  TotOSC=GetNumObjectsFound(cCurrentModuleObject)
  ALLOCATE(OSC(TotOSC))

  OSCNum=0
  DO Loop=1,TotOSC
    CALL GetObjectItem(cCurrentModuleObject,Loop,cAlphaArgs,NumAlphas, &
                       rNumericArgs,NumProps,IOSTAT,  &
                   AlphaBlank=lAlphaFieldBlanks,NumBlank=lNumericFieldBlanks,  &
                   AlphaFieldnames=cAlphaFieldNames,NumericFieldNames=cNumericFieldNames)
    ErrorInName=.false.
    IsBlank=.false.
    CALL VerifyName(cAlphaArgs(1),OSC%Name,OSCNum,ErrorInName,IsBlank,TRIM(cCurrentModuleObject)//' Name')
    IF (ErrorInName) THEN
      ErrorsFound=.true.
      CYCLE
    ENDIF

    OSCNum=OSCNum+1
    OSC(OSCNum)%Name            = cAlphaArgs(1)
    OSC(OSCNum)%SurfFilmCoef    = rNumericArgs(1)
    OSC(OSCNum)%ConstTemp       = rNumericArgs(2)  !  This will be replaced if  schedule is used
    OSC(OSCNum)%ConstTempCoef   = rNumericArgs(3)  !  This multiplier is used (even with schedule).  It should normally be 1.0
    OSC(OSCNum)%ExtDryBulbCoef  = rNumericArgs(4)
    OSC(OSCNum)%GroundTempCoef  = rNumericArgs(5)
    OSC(OSCNum)%WindSpeedCoef   = rNumericArgs(6)
    OSC(OSCNum)%ZoneAirTempCoef = rNumericArgs(7)
    OSC(OSCNum)%SinusoidPeriod  = rNumericArgs(8)

    IF(( .not. lAlphaFieldBlanks(2)) .and. (NumAlphas /= 1)) THEN  !  Const temp will come from schedule specified below.
      OSC(OSCNum)%ConstTempScheduleName = cAlphaArgs(2)
      IF (OSC(OSCNum)%ConstTempScheduleName /= Blank) THEN
        OSC(OSCNum)%ConstTempScheduleIndex=GetScheduleIndex(OSC(OSCNum)%ConstTempScheduleName)
        IF (OSC(OSCNum)%ConstTempScheduleIndex == 0) THEN
          CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(cAlphaArgs(1))//  &
            '", invalid '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2)))
          ErrorsFound=.true.
        ENDIF
      ENDIF
    ENDIF

    IF (.NOT. lAlphaFieldBlanks(3)) THEN

      IF (SameString(cAlphaArgs(3), 'No')) THEN
        OSC(OSCNum)%SinusoidalConstTempCoef = .FALSE.
      ELSEIF (SameString(cAlphaArgs(3), 'Yes')) THEN
        OSC(OSCNum)%SinusoidalConstTempCoef = .True.
      ELSE
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(cAlphaArgs(1))//  &
            '", invalid '//TRIM(cAlphaFieldNames(3))//'="'//TRIM(cAlphaArgs(3)))
        ErrorsFound=.true.
      ENDIF
    ENDIF

    IF (rNumericArgs(1) > 0.0d0 .and. .not. ANY(rNumericArgs(3:7) /= 0.0d0) &
         .AND. (.not. OSC(OSCNum)%SinusoidalConstTempCoef)) THEN
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(cAlphaArgs(1))//  &
              '" has zeros for all coefficients.')
      CALL ShowContinueError('...The outdoor air temperature for surfaces using this OtherSideCoefficients '//  &
        'object will always be 0C.')
    ENDIF

    IF (rNumericArgs(1) <= 0.0d0 .and. .not. ANY(rNumericArgs(3:7) /= 0.0d0) &
         .AND. (.not. OSC(OSCNum)%SinusoidalConstTempCoef)) THEN
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//'="'//TRIM(cAlphaArgs(1))//  &
              '" has zeros for all coefficients.')
      CALL ShowContinueError('...The outside surface temperature for surfaces using this OtherSideCoefficients '//  &
        'object will always be 0C.')
    ENDIF

    OSC(OSCNum)%TPreviousCoef  = rNumericArgs(9)

    IF (.NOT. lNumericFieldBlanks(10)) THEN
      OSC(OSCNum)%MinLimitPresent = .TRUE.
      OSC(OSCNum)%MinTempLimit   = rNumericArgs(10)
      cOSCLimitsString = RoundSigDigits(rNumericArgs(10),3)
    ELSE
      cOSCLimitsString = 'N/A'
    ENDIF
    IF (.NOT. lNumericFieldBlanks(11)) THEN
      OSC(OSCNum)%MaxLimitPresent = .TRUE.
      OSC(OSCNum)%MaxTempLimit   = rNumericArgs(11)
      cOSCLimitsString = TRIM(cOSCLimitsString)//','//TRIM(RoundSigDigits(rNumericArgs(10),3))
    ELSE
      cOSCLimitsString = TRIM(cOSCLimitsString)//','//'N/A'
    ENDIF

  ENDDO

  DO Loop=1,TotOSC
    IF (Loop == 1) THEN
      WRITE(OutputFileInits,OSCFormat1)
    ENDIF
    IF (OSC(Loop)%SurfFilmCoef > 0.0d0) THEN
      cAlphaArgs(1)=RoundSigDigits(OSC(Loop)%SurfFilmCoef,3)
      CALL SetupOutputVariable('Surface Other Side Coefficients Exterior Air Drybulb Temperature [C]',OSC(Loop)%OSCTempCalc, &
                                 'System','Average',OSC(Loop)%Name)
    ELSE
      cAlphaArgs(1)='N/A'
    ENDIF
    IF (OSC(Loop)%ConstTempScheduleIndex /= 0) THEN
      cAlphaArgs(2)=OSC(Loop)%ConstTempScheduleName
      WRITE(OutputFileInits,'(A)') 'Other Side Coefficients,'//TRIM(OSC(Loop)%Name)//','//TRIM(cAlphaArgs(1))//','// &
        'N/A,'//TRIM(RoundSigDigits(OSC(Loop)%ConstTempCoef,3))//','// &
        TRIM(RoundSigDigits(OSC(Loop)%ExtDryBulbCoef,3))//','//TRIM(RoundSigDigits(OSC(Loop)%GroundTempCoef,3))//','// &
        TRIM(RoundSigDigits(OSC(Loop)%WindSpeedCoef,3))//','//TRIM(RoundSigDigits(OSC(Loop)%ZoneAirTempCoef,3))//','// &
        TRIM(cAlphaArgs(2))//','//TRIM(cAlphaArgs(3))//','//TRIM(RoundSigDigits(OSC(Loop)%SinusoidPeriod,3))//','// &
        TRIM(RoundSigDigits(OSC(Loop)%TPreviousCoef,3))//','//TRIM(cOSCLimitsString)
    ELSE
      cAlphaArgs(2)='N/A'
      WRITE(OutputFileInits,'(A)') 'Other Side Coefficients,'//TRIM(OSC(Loop)%Name)//','//TRIM(cAlphaArgs(1))//','// &
        TRIM(RoundSigDigits(OSC(Loop)%ConstTemp,2))//','//TRIM(RoundSigDigits(OSC(Loop)%ConstTempCoef,3))//','// &
        TRIM(RoundSigDigits(OSC(Loop)%ExtDryBulbCoef,3))//','//TRIM(RoundSigDigits(OSC(Loop)%GroundTempCoef,3))//','// &
        TRIM(RoundSigDigits(OSC(Loop)%WindSpeedCoef,3))//','//TRIM(RoundSigDigits(OSC(Loop)%ZoneAirTempCoef,3))//','// &
        TRIM(cAlphaArgs(2))//','//TRIM(cAlphaArgs(3))//','//TRIM(RoundSigDigits(OSC(Loop)%SinusoidPeriod,3))//','// &
        TRIM(RoundSigDigits(OSC(Loop)%TPreviousCoef,3))//','//TRIM(cOSCLimitsString)
    ENDIF

  ENDDO
  RETURN

END SUBROUTINE GetOSCData

SUBROUTINE GetOSCMData(ErrorsFound)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Brent Griffith
          !       DATE WRITTEN   November 2004
          !       MODIFIED       na
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! This subroutine gets the OtherSideConditionsModel data.

          ! METHODOLOGY EMPLOYED:
          ! na

          ! REFERENCES:
          ! derived from GetOSCData subroutine by Linda Lawrie

          !  OtherSideConditionsModel,
          !      \memo This object sets up modifying the other side conditions for a surface from other model results.
          !  A1, \field OtherSideConditionsModel Name
          !      \required-field
          !      \reference OSCMNames
          !      \reference OutFaceEnvNames
          !  A2; \field Type of Model to determine Boundary Conditions
          !      \type choice
          !      \key Transpired Collector
          !      \key Vented PV Cavity
          !      \key Hybrid PV Transpired Collector

          ! USE STATEMENTS:
  USE DataIPShortCuts
  USE InputProcessor, ONLY: GetNumObjectsFound, GetObjectItem, FindItemInList, VerifyName

  IMPLICIT NONE    ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
  LOGICAL, INTENT(INOUT) :: ErrorsFound

          ! SUBROUTINE PARAMETER DEFINITIONS:
  CHARACTER(len=*), PARAMETER :: OSCMFormat1="('! <Other Side Conditions Model>,Name,Class')"

          ! INTERFACE BLOCK SPECIFICATIONS
          ! na

          ! DERIVED TYPE DEFINITIONS
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
  INTEGER NumAlphas
  INTEGER NumProps
  INTEGER Loop
  INTEGER IOSTAT
  INTEGER OSCMNum
  LOGICAL ErrorInName
  LOGICAL IsBlank

  cCurrentModuleObject='SurfaceProperty:OtherSideConditionsModel'
  TotOSCM=GetNumObjectsFound(cCurrentModuleObject)
  ALLOCATE(OSCM(TotOSCM))
  ! OSCM is already initialized in derived type defn.

  OSCMNum=0
  DO Loop=1,TotOSCM
    CALL GetObjectItem(cCurrentModuleObject,Loop,cAlphaArgs,NumAlphas, &
                       rNumericArgs,NumProps,IOSTAT)
    ErrorInName=.false.
    IsBlank=.false.
    CALL VerifyName(cAlphaArgs(1),OSCM%Name,OSCMNum,ErrorInName,IsBlank,TRIM(cCurrentModuleObject)//' Name')
    IF (ErrorInName) THEN
      ErrorsFound=.true.
      CYCLE
    ENDIF

    OSCMNum=OSCMNum+1
    OSCM(OSCMNum)%Name            = cAlphaArgs(1)
    ! Note no validation of the below at this time:
    OSCM(OSCMNum)%Class           = cAlphaArgs(2)
    ! setup output vars for modeled coefficients
    CALL SetupOutputVariable('Surface Other Side Conditions Modeled Convection Air Temperature [C]',OSCM(OSCMNum)%TConv, &
                               'System','Average',OSCM(OSCMNum)%Name)
    CALL SetupOutputVariable('Surface Other Side Conditions Modeled Convection Heat Transfer Coefficient [W/m2-K]', &
                              OSCM(OSCMNum)%HConv, &
                               'System','Average',OSCM(OSCMNum)%Name)
    CALL SetupOutputVariable('Surface Other Side Conditions Modeled Radiation Temperature [C]',OSCM(OSCMNum)%TRad, &
                               'System','Average',OSCM(OSCMNum)%Name)
    CALL SetupOutputVariable('Surface Other Side Conditions Modeled Radiation Heat Transfer Coefficient [W/m2-K]', &
                              OSCM(OSCMNum)%HRad, &
                               'System','Average',OSCM(OSCMNum)%Name)

    IF (AnyEnergyManagementSystemInModel) THEN
      CALL SetupEMSActuator('Other Side Boundary Conditions',  OSCM(OSCMNum)%Name, &
                           'Convection Bulk Air Temperature', '[C]', &
                           OSCM(OSCMNum)%EMSOverrideOnTConv, &
                           OSCM(OSCMNum)%EMSOverrideTConvValue)
      CALL SetupEMSActuator('Other Side Boundary Conditions',  OSCM(OSCMNum)%Name, &
                           'Convection Heat Transfer Coefficient', '[W/m2-K]', &
                           OSCM(OSCMNum)%EMSOverrideOnHConv, &
                           OSCM(OSCMNum)%EMSOverrideHConvValue)
      CALL SetupEMSActuator('Other Side Boundary Conditions',  OSCM(OSCMNum)%Name, &
                           'Radiation Effective Temperature', '[C]', &
                           OSCM(OSCMNum)%EMSOverrideOnTRad, &
                           OSCM(OSCMNum)%EMSOverrideTRadValue)
      CALL SetupEMSActuator('Other Side Boundary Conditions',  OSCM(OSCMNum)%Name, &
                           'Radiation Linear Heat Transfer Coefficient', '[W/m2-K]', &
                           OSCM(OSCMNum)%EMSOverrideOnHrad, &
                           OSCM(OSCMNum)%EMSOverrideHradValue)
    ENDIF
  ENDDO

  DO Loop=1,TotOSCM
    IF (Loop == 1) THEN
      WRITE(OutputFileInits,OSCMFormat1)
    ENDIF
    WRITE(OutputFileInits,'(A)') 'Other Side Conditions Model,'//TRIM(OSCM(Loop)%Name)//','//TRIM(OSCM(Loop)%Class)
  ENDDO

  RETURN

END SUBROUTINE GetOSCMData

SUBROUTINE GetMovableInsulationData(ErrorsFound)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Linda Lawrie
          !       DATE WRITTEN   May 2000
          !       MODIFIED       na
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! This subroutine gets the movable insulation data that can be associated with
          ! a surface.

          ! METHODOLOGY EMPLOYED:
          ! na

          ! REFERENCES:
  ! Movable Insulation Definition
  ! SurfaceControl:MovableInsulation,
  !       \memo Exterior or Interior Insulation on opaque surfaces
  !   A1, \field Insulation Type
  !       \required-field
  !       \type choice
  !       \key Outside
  !       \key Inside
  !   A2, \field Surface Name
  !       \required-field
  !       \type object-list
  !       \object-list SurfaceNames
  !   A3, \field Material Name
  !       \required-field
  !       \object-list MaterialName
  !   A4; \field Schedule Name
  !        \required-field
  !        \type object-list
  !        \object-list ScheduleNames

          ! USE STATEMENTS:
    USE DataIPShortCuts
    USE InputProcessor, ONLY: GetNumObjectsFound, GetObjectItem, FindItemInList, VerifyName, SameString
    USE ScheduleManager, ONLY: GetScheduleIndex
    USE General, ONLY: TrimSigDigits,RoundSigDigits

  IMPLICIT NONE    ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
  LOGICAL, INTENT(INOUT) :: ErrorsFound ! If errors found in input

          ! SUBROUTINE PARAMETER DEFINITIONS:
          ! na

          ! INTERFACE BLOCK SPECIFICATIONS
          ! na

          ! DERIVED TYPE DEFINITIONS
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
  INTEGER NAlphas
  INTEGER NNums
  INTEGER IOSTAT
  INTEGER Loop
  INTEGER NMatInsul
  INTEGER SurfNum
  INTEGER MaterNum
  INTEGER SchNum
  INTEGER InslType

  cCurrentModuleObject='SurfaceControl:MovableInsulation'
  NMatInsul=GetNumObjectsFound(cCurrentModuleObject)
  DO Loop=1,NMatInsul
    CALL GetObjectItem(cCurrentModuleObject,Loop,cAlphaArgs,NAlphas,rNumericArgs,NNums,IOSTAT,  &
                   AlphaBlank=lAlphaFieldBlanks,NumBlank=lNumericFieldBlanks,  &
                   AlphaFieldnames=cAlphaFieldNames,NumericFieldNames=cNumericFieldNames)
    SurfNum=FindItemInList(cAlphaArgs(2),SurfaceTmp%Name,TotSurfaces)
    MaterNum=FindItemInList(cAlphaArgs(3),Material%Name,TotMaterials)
    SchNum=GetScheduleIndex(cAlphaArgs(4))
    IF (SameString(cAlphaArgs(1),'Outside')) THEN
      InslType=1
    ELSEIF (SameString(cAlphaArgs(1),'Inside')) THEN
      InslType=2
    ELSE
      InslType=0
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//', '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))//  &
         '", invalid data.')
      CALL ShowContinueError(' invalid '//TRIM(cAlphaFieldNames(1))//'="'//TRIM(cAlphaArgs(1))//  &
         '", [should be Inside or Outside]')
      ErrorsFound=.false.
    ENDIF
    IF (SurfNum == 0) THEN
      CALL ShowSevereError(TRIM(cCurrentModuleObject)//', '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))//  &
         '", invalid data.')
      CALL ShowContinueError(' invalid (not found) '//TRIM(cAlphaFieldNames(2)))
      ErrorsFound=.true.
    ELSE
      IF (MaterNum == 0) THEN
        CALL ShowSevereError(TRIM(cCurrentModuleObject)//', '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))//  &
           '", invalid data.')
        CALL ShowContinueError(' invalid (not found) '//TRIM(cAlphaFieldNames(3))//'="'//TRIM(cAlphaArgs(3))//'"')
        ErrorsFound=.true.
      ELSE
        IF (SchNum == 0) THEN
          CALL ShowSevereError(TRIM(cCurrentModuleObject)//', '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))//  &
           '", invalid data.')
          CALL ShowContinueError(' invalid (not found) '//TRIM(cAlphaFieldNames(4))//'="'//TRIM(cAlphaArgs(4))//'"')
          ErrorsFound=.true.
        ELSE
          SELECT CASE (InslType)
          CASE (1)
            IF (SurfaceTmp(SurfNum)%MaterialMovInsulExt > 0) THEN
              CALL ShowSevereError(TRIM(cCurrentModuleObject)//', '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))//  &
                 '", already assigned.')
              CALL ShowContinueError('"Outside", was already assigned Material="'//  &
                 trim(Material(SurfaceTmp(SurfNum)%MaterialMovInsulInt)%Name)//'".')
              CALL ShowContinueError('attempting to assign Material="'//trim(Material(MaterNum)%Name)//'".')
              ErrorsFound=.true.
            ENDIF
            SurfaceTmp(SurfNum)%MaterialMovInsulExt=MaterNum
            SurfaceTmp(SurfNum)%SchedMovInsulExt=SchNum
            IF (Material(MaterNum)%Resistance <= 0.0d0) THEN
              IF (Material(MaterNum)%Conductivity <= 0.0d0 .or. Material(MaterNum)%Thickness <= 0.0d0) THEN
                CALL ShowSevereError(TRIM(cCurrentModuleObject)//', '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))//  &
                   '", invalid material.')
                CALL ShowContinueError('"Outside", invalid material for movable insulation.')
                CALL ShowContinueError('Material="'//trim(Material(MaterNum)%Name)//'",'//  &
                   'Resistance=['//trim(RoundSigDigits(Material(MaterNum)%Resistance,3))//  &
                   '], must be > 0 for use in Movable Insulation.')
                ErrorsFound=.true.
              ELSEIF (Material(MaterNum)%Conductivity > 0.0d0) THEN
                Material(MaterNum)%Resistance=Material(MaterNum)%Thickness/Material(MaterNum)%Conductivity
              ENDIF
            ENDIF
            IF (Material(MaterNum)%Conductivity <= 0.0d0) THEN
              IF (Material(MaterNum)%Resistance <= 0.0d0) THEN
                CALL ShowSevereError(TRIM(cCurrentModuleObject)//', '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))//  &
                   '", invalid material.')
                CALL ShowContinueError('"Outside", invalid material for movable insulation.')
                CALL ShowContinueError('Material="'//trim(Material(MaterNum)%Name)//'",'//  &
                   'Conductivity=['//trim(RoundSigDigits(Material(MaterNum)%Conductivity,3))//  &
                   '], must be > 0 for use in Movable Insulation.')
                ErrorsFound=.true.
              ENDIF
            ENDIF
          CASE (2)
            IF (SurfaceTmp(SurfNum)%MaterialMovInsulInt > 0) THEN
              CALL ShowSevereError(TRIM(cCurrentModuleObject)//', '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))//  &
                 '", already assigned.')
              CALL ShowContinueError('"Inside", was already assigned Material="'//  &
                 trim(Material(SurfaceTmp(SurfNum)%MaterialMovInsulInt)%Name)//'".')
              CALL ShowContinueError('attempting to assign Material="'//trim(Material(MaterNum)%Name)//'".')
              ErrorsFound=.true.
            ENDIF
            SurfaceTmp(SurfNum)%MaterialMovInsulInt=MaterNum
            SurfaceTmp(SurfNum)%SchedMovInsulInt=SchNum
            IF (Material(MaterNum)%Resistance <= 0.0d0) THEN
              IF (Material(MaterNum)%Conductivity <= 0.0d0 .or. Material(MaterNum)%Thickness <= 0.0d0) THEN
                CALL ShowSevereError(TRIM(cCurrentModuleObject)//', '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))//  &
                   '", invalid material.')
                CALL ShowContinueError('"Inside", invalid material for movable insulation.')
                CALL ShowContinueError('Material="'//trim(Material(MaterNum)%Name)//'",'//  &
                   'Resistance=['//trim(RoundSigDigits(Material(MaterNum)%Resistance,3))//  &
                   '], must be > 0 for use in Movable Insulation.')
                ErrorsFound=.true.
              ELSEIF (Material(MaterNum)%Conductivity > 0.0d0) THEN
                Material(MaterNum)%Resistance=Material(MaterNum)%Thickness/Material(MaterNum)%Conductivity
              ENDIF
            ENDIF
          CASE DEFAULT
          END SELECT
          IF (SurfaceTmp(SurfNum)%Class == SurfaceClass_Window) THEN
            CALL ShowSevereError(TRIM(cCurrentModuleObject)//', '//TRIM(cAlphaFieldNames(2))//'="'//TRIM(cAlphaArgs(2))//'"')
            CALL ShowContinueError('invalid use on a Window. Use WindowProperty:ShadingControl instead.')
            ErrorsFound=.true.
          ENDIF
        ENDIF
      ENDIF
    ENDIF
  ENDDO

  RETURN

END SUBROUTINE GetMovableInsulationData

SUBROUTINE CalculateZoneVolume(ErrorsFound,CeilingHeightEntered)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Legacy Code
          !       DATE WRITTEN   1992-1994
          !       MODIFIED       Sep 2007
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! This subroutine calculates the volume (m3) of a zone using the
          ! surfaces as possible.

          ! METHODOLOGY EMPLOYED:
          ! Uses surface area information for calculations.  Modified to use the
          ! user-entered ceiling height (x floor area, if applicable) instead of using
          ! the calculated volume when the user enters the ceiling height.

          ! REFERENCES:
          ! Legacy Code (IBLAST)

          ! USE STATEMENTS:
  USE InputProcessor, ONLY: FindItemInList,GetNumSectionsFound
  USE Vectors
  USE General, ONLY: RoundSigDigits

  IMPLICIT NONE    ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
  LOGICAL, INTENT(INOUT) :: ErrorsFound ! If errors found in input
  LOGICAL, DIMENSION(:), INTENT(IN)    :: CeilingHeightEntered

          ! SUBROUTINE PARAMETER DEFINITIONS:
  CHARACTER(len=*), PARAMETER :: VolFmt="(F20.2)"

          ! INTERFACE BLOCK SPECIFICATIONS
          ! na

          ! DERIVED TYPE DEFINITIONS
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
  REAL(r64) MinimumVolume        ! The minimum allowable Zone volume (equivalent to a ceiling height of 2.5 meters)
  REAL(r64) SumAreas             ! Sum of the Zone surface areas that are not "internal mass"
  REAL(r64) SurfCount            ! Surface Count
  INTEGER SurfNum           ! Loop counter for surfaces
  INTEGER ZoneNum           ! Loop counter for Zones
  LOGICAL ErrorFlag
  REAL(r64) TempVolume           ! Temporary for calculating volume
  type(polyhedron) :: ZoneStruct
  integer, allocatable, dimension(:) :: surfacenotused
  integer :: notused
  INTEGER NFaces
  INTEGER NActFaces
  REAL(r64) CalcVolume
  LOGICAL initmsg
  integer iside
  LOGICAL :: ShowZoneSurfaces=.false.
  LOGICAL :: ShowZoneSurfaceHeaders=.true.
  INTEGER, SAVE :: ErrCount=0

  initmsg=.true.
  ShowZoneSurfaces=(GetNumSectionsFound('SHOWZONESURFACES_DEBUG') > 0)

  DO ZoneNum = 1, NumOfZones

    IF (.not. Zone(ZoneNum)%HasFloor) THEN
      CALL ShowWarningError('No floor exists in Zone="'//TRIM(Zone(ZoneNum)%Name)//  &
         '", zone floor area is zero. All values for this zone that are entered per floor area will be zero.')
    ENDIF

    SumAreas=0.0d0
    SurfCount=0.0d0
    NFaces=Zone(ZoneNum)%SurfaceLast-Zone(ZoneNum)%SurfaceFirst+1
    notused=0
    ZoneStruct%NumSurfaceFaces=NFaces
    ALLOCATE(ZoneStruct%SurfaceFace(NFaces))
    NActFaces=0
    ALLOCATE(surfacenotused(NFaces))
    surfacenotused=0

    DO SurfNum=Zone(ZoneNum)%SurfaceFirst,Zone(ZoneNum)%SurfaceLast

      ! Only include Base Surfaces in Calc.

      IF (Surface(SurfNum)%Class /= SurfaceClass_Wall .and. Surface(SurfNum)%Class /= SurfaceClass_Floor .and. &
          Surface(SurfNum)%Class /= SurfaceClass_Roof) THEN
        notused=notused+1
        surfacenotused(notused)=SurfNum
        CYCLE
      ENDIF

      NActFaces=NActFaces+1
      ALLOCATE(ZoneStruct%SurfaceFace(NActFaces)%FacePoints(Surface(SurfNum)%Sides))
      ZoneStruct%SurfaceFace(NActFaces)%NSides=Surface(SurfNum)%Sides
      ZoneStruct%SurfaceFace(NActFaces)%SurfNum=SurfNum
      ZoneStruct%SurfaceFace(NActFaces)%FacePoints(1:Surface(SurfNum)%Sides)=Surface(SurfNum)%Vertex(1:Surface(SurfNum)%Sides)
      CALL CreateNewellAreaVector(ZoneStruct%SurfaceFace(NActFaces)%FacePoints,ZoneStruct%SurfaceFace(NActFaces)%NSides,  &
                              ZoneStruct%SurfaceFace(NActFaces)%NewellAreaVector)
      SumAreas=SumAreas+VecLength(ZoneStruct%SurfaceFace(NActFaces)%NewellAreaVector)
    ENDDO
    ZoneStruct%NumSurfaceFaces=NActFaces
    SurfCount=REAL(NActFaces,r64)
    CALL CalcPolyhedronVolume(ZoneStruct,CalcVolume)

    IF(Zone(ZoneNum)%FloorArea > 0.0d0) THEN
      MinimumVolume=Zone(ZoneNum)%FloorArea * 2.5d0
      IF (Zone(ZoneNum)%CeilingHeight > 0.0d0) THEN
        MinimumVolume=Zone(ZoneNum)%FloorArea*Zone(ZoneNum)%CeilingHeight
      ENDIF
    ELSE
      IF (SurfCount > 0) THEN
        MinimumVolume=SQRT(SumAreas/SurfCount)**3
      ELSE
        MinimumVolume=0.0d0
      ENDIF
    ENDIF
    IF (CalcVolume > 0.0d0) THEN
      TempVolume=CalcVolume
    ELSE
      TempVolume=MinimumVolume
    ENDIF

    IF (Zone(ZoneNum)%Volume > 0.0d0) THEN   ! User entered zone volume, produce message if not near calculated
      IF (TempVolume > 0.0d0) THEN
        IF (ABS(TempVolume-Zone(ZoneNum)%Volume)/Zone(ZoneNum)%Volume  > .05d0) THEN
          ErrCount=ErrCount+1
          IF (ErrCount == 1 .and. .not. DisplayExtraWarnings) THEN
            IF (initmsg) THEN
              CALL ShowMessage('Note that the following warning(s) may/will occur if you have not enclosed your zone completely.')
              initmsg=.false.
            ENDIF
            CALL ShowWarningError('Entered Zone Volumes differ from calculated zone volume(s).')
            CALL ShowContinueError('...use Output:Diagnostics,DisplayExtraWarnings; to show more details on individual zones.')
          ENDIF
          IF (DisplayExtraWarnings) THEN
            IF (initmsg) THEN
              CALL ShowMessage('Note that the following warning(s) may/will occur if you have not enclosed your zone completely.')
              initmsg=.false.
            ENDIF
            ! Warn user of using specified Zone Volume
            CALL ShowWarningError('Entered Volume entered for Zone="'//TRIM(Zone(ZoneNum)%Name)// &
                                  '" significantly different from calculated Volume')
            CALL ShowContinueError('Entered Zone Volume value='//TRIM(RoundSigDigits(Zone(ZoneNum)%Volume,2))//  &
                                   ', Calculated Zone Volume value='//TRIM(RoundSigDigits(TempVolume,2))// &
                                  ', entered volume will be used in calculations.')
          ENDIF
        ENDIF
      ENDIF
    ELSEIF (CeilingHeightEntered(ZoneNum)) THEN   ! User did not enter zone volume, but entered ceiling height
      IF (Zone(ZoneNum)%FloorArea > 0.0d0) THEN
        Zone(ZoneNum)%Volume=Zone(ZoneNum)%FloorArea*Zone(ZoneNum)%CeilingHeight
      ELSE ! ceiling height entered but floor area zero
        Zone(ZoneNum)%Volume=TempVolume
      ENDIF
    ELSE  ! Neither ceiling height nor volume entered
      Zone(ZoneNum)%Volume=TempVolume
    ENDIF

    IF (Zone(ZoneNum)%Volume <= 0.0d0) THEN
      CALL ShowSevereError('Indicated Zone Volume <= 0.0 for Zone='//TRIM(Zone(ZoneNum)%Name))
      CALL ShowContinueError('Zone Volume calculated was='//TRIM(RoundSigDigits(Zone(ZoneNum)%Volume,2)))
    ENDIF

    IF (ShowZoneSurfaces) THEN
      IF (ShowZoneSurfaceHeaders) THEN
        write(outputfiledebug,*) '==================================='
        write(outputfiledebug,*) 'showing zone surfaces used and not used in volume calculation'
        write(outputfiledebug,*) 'for volume calculation, only floors, walls and roofs/ceilings are used'
        write(outputfiledebug,*) 'surface class, 1=wall, 2=floor, 3=roof/ceiling'
        write(outputfiledebug,*) 'unused surface class(es), 5=internal mass, 11=window, 12=glass door'
        write(outputfiledebug,*) '                          13=door, 14=shading, 15=overhang, 16=fin'
        write(outputfiledebug,*) '                          17=TDD Dome, 18=TDD Diffuser'
        ShowZoneSurfaceHeaders=.false.
      ENDIF
      write(outputfiledebug,*) '==================================='
      write(outputfiledebug,*) 'zone=',trim(zone(zonenum)%name),' calc volume=',calcvolume
      write(outputfiledebug,*) ' nsurfaces=',nfaces,' nactual=',nactfaces
    ENDIF
    do SurfNum=1,ZoneStruct%NumSurfaceFaces
      IF (ShowZoneSurfaces) THEN
        if (surfnum <= nactfaces) then
          write(outputfiledebug,*) 'surface=',zonestruct%surfaceface(surfnum)%surfnum,  &
                                   ' nsides=',zonestruct%surfaceface(surfnum)%Nsides
          write(outputfiledebug,*) 'surface name=',trim(surface(zonestruct%surfaceface(surfnum)%surfnum)%name),  &
                                    ' class=',surface(zonestruct%surfaceface(surfnum)%surfnum)%class
          write(outputfiledebug,*) 'area=',surface(zonestruct%surfaceface(surfnum)%surfnum)%grossarea
          do iside=1, zonestruct%surfaceface(surfnum)%Nsides
            write(outputfiledebug,*) zonestruct%surfaceface(surfnum)%facepoints(iside)
          enddo
        endif
      ENDIF
      deallocate(ZoneStruct%SurfaceFace(SurfNum)%FacePoints)
    enddo
    IF (ShowZoneSurfaces) THEN
      do surfnum=1,notused
        write(outputfiledebug,*) 'notused:surface=',surfacenotused(surfnum),' name=',  &
          trim(surface(surfacenotused(surfnum))%name),  &
          ' class=',surface(surfacenotused(surfnum))%class
      enddo
    ENDIF

    deallocate(ZoneStruct%SurfaceFace)
    deallocate(surfacenotused)

  END DO

  ErrorFlag=.false.
  DO ZoneNum=1,NumOfZones
    IF (Zone(ZoneNum)%Volume <= 0.0d0) ErrorFlag=.true.
  END DO
  IF (ErrorFlag) THEN
    CALL ShowSevereError('All ZONE Volumes must be > 0.0')
    ErrorsFound=.true.
  ENDIF

  RETURN

END SUBROUTINE CalculateZoneVolume

SUBROUTINE ProcessSurfaceVertices(ThisSurf,ErrorsFound)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Legacy Code (Walton)
          !       DATE WRITTEN   1976
          !       MODIFIED        FW, Mar 2002: Add triangular windows
          !                       FW, May 2002: modify test for 4-sided but non-rectangular subsurfaces
          !                       FW, Sep 2002: add shape for base surfaces (walls and detached shading surfaces)
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! This subroutine processes each surface into the vertex representation used
          ! by the shading procedures.
          ! This routine depends on the surfaces coming in:
          !  Base Surface
          !   SubSurface (Window/Door)
          !   SubSurface
          !  Base Surface
          !   SubSurface
          !   SubSurface
          !  Thus, some attributes of the "Base Surface" must be SAVEd.

          ! METHODOLOGY EMPLOYED:
          ! Detached Shading, Base Surfaces, Attached Shading surfaces are represented in the
          ! same manner as original.  Subsurfaces (windows, doors) are a "relative coordinate".

          ! REFERENCES:
          ! na

          ! USE STATEMENTS:
  USE General, ONLY: TrimSigDigits
  USE Vectors

  IMPLICIT NONE    ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
  INTEGER, INTENT(IN)    :: ThisSurf    ! Surface Number
  LOGICAL, INTENT(INOUT) :: ErrorsFound

          ! SUBROUTINE PARAMETER DEFINITIONS:
  CHARACTER(len=*), PARAMETER :: RoutineName='ProcessSurfaceVertices: '

          ! INTERFACE BLOCK SPECIFICATIONS
          ! na

          ! DERIVED TYPE DEFINITIONS
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
          ! na

          ! LOCAL VARIABLES
!  REAL(r64) :: X00    ! Intermediate Result
!  REAL(r64) :: Y00    ! Intermediate Result
!  REAL(r64) :: Z00    ! Intermediate Result
!  REAL(r64) :: A(3,3) ! Surface Rotation Matrix
!  REAL(r64), SAVE :: B(3,3) ! Inverse Of Rotation Matrix
  REAL(r64) :: X1    ! Intermediate Result
  REAL(r64) :: Y1    ! Intermediate Result
  REAL(r64) :: Z1    ! Intermediate Result
  REAL(r64), SAVE :: XSHIFT  ! Shift of X to Lower Left Corner
  REAL(r64), SAVE :: YSHIFT  ! Shift of Y to Lower Left Corner
  REAL(r64)  :: XLLC   ! X-coordinate of lower left corner
  REAL(r64)  :: YLLC   ! Y-coordinate of lower left corner
  REAL(r64)  :: ZLLC   ! Z-coordinate of lower left corner
  REAL(r64), ALLOCATABLE, DIMENSION(:), SAVE  :: X
  REAL(r64), ALLOCATABLE, DIMENSION(:), SAVE  :: Y
  REAL(r64), ALLOCATABLE, DIMENSION(:), SAVE  :: Z
  LOGICAL :: OneTimeFlag=.true.
!  INTEGER :: I  ! Loop Control
!  INTEGER :: J  ! Loop Control
  INTEGER :: N  ! Vertex Number in Loop
  INTEGER ThisBaseSurface  ! Current base surface
  REAL(r64) Xp
  REAL(r64) Yp
  REAL(r64) Zp
  REAL(r64), SAVE :: BaseCosAzimuth
  REAL(r64), SAVE :: BaseCosTilt
  REAL(r64), SAVE :: BaseSinAzimuth
  REAL(r64), SAVE :: BaseSinTilt
  REAL(r64), SAVE :: BaseXLLC
  REAL(r64), SAVE :: BaseYLLC
  REAL(r64), SAVE :: BaseZLLC
  REAL(r64) SurfWorldAz  ! Surface Azimuth (facing)
  REAL(r64) SurfTilt     ! Surface Tilt
  type (planeeq) BasePlane
!  type (planeeq) PlanarEQ
!  type (vector), dimension(3) :: TriVect
!  REAL(r64) testval
!  INTEGER ploop
!  INTEGER vloop
  type (vector) TVect
  type (vector) CoordinateTransVector
  INTEGER ThisShape
  LOGICAL BaseSurface   ! True if a base surface or a detached shading surface
  REAL(r64) ThisSurfAz
  REAL(r64) ThisSurfTilt
  REAL(r64) ThisReveal
  REAL(r64) ThisWidth
  REAL(r64) ThisHeight
  INTEGER FrDivNum ! Frame/divider number
  REAL(r64) FrWidth    ! Frame width for exterior windows (m)
  REAL(r64) FrArea     ! Frame area for exterior windows(m2)
  REAL(r64) DivWidth   ! Divider width for exterior windows (m)
  REAL(r64) DivArea    ! Divider area for exterior windows (m2)
  REAL(r64) DivFrac    ! Fraction of divider area without overlaps
  LOGICAL ErrorInSurface ! false/true, depending on pass through routine
  REAL(r64) Diagonal1  ! Length of diagonal of 4-sided figure (m)
  REAL(r64) Diagonal2  ! Length of diagonal of 4-sided figure (m)
  LOGICAL SError
  LOGICAL HeatTransSurf
  LOGICAL IsCoplanar
  REAL(r64) OutOfLine
  INTEGER LastVertexInError

  ErrorInSurface=.false.

  IF (OneTimeFlag) THEN
    ALLOCATE(X(MaxVerticesPerSurface))
    ALLOCATE(Y(MaxVerticesPerSurface))
    ALLOCATE(Z(MaxVerticesPerSurface))
    X=0.0d0
    Y=0.0d0
    Z=0.0d0
    OneTimeFlag=.false.
  ENDIF

! Categorize this surface

   IF (Surface(ThisSurf)%BaseSurf == 0 .or. Surface(ThisSurf)%BaseSurf == ThisSurf) THEN
     BaseSurface=.true.
   ELSE
     BaseSurface=.false.
   ENDIF

   ThisBaseSurface=Surface(ThisSurf)%BaseSurf  ! Dont know if this is still needed or not
   HeatTransSurf = Surface(ThisSurf)%HeatTransSurf

   ! Kludge for daylighting shelves
   IF (Surface(ThisSurf)%ShadowingSurf) THEN
     ThisBaseSurface = ThisSurf
     HeatTransSurf = .TRUE.
   END IF

   !IF (Surface(ThisSurf)%Name(1:3) /= 'Mir') THEN
   IF (.NOT. Surface(ThisSurf)%MirroredSurf) THEN
     CALL CalcCoPlanarNess(Surface(ThisSurf)%Vertex,Surface(ThisSurf)%Sides,IsCoplanar,OutOfLine,LastVertexInError)
     IF (.not. IsCoPlanar) THEN
       IF (OutOfLine > .01d0) THEN
         CALL ShowSevereError(RoutineName//'Suspected non-planar surface:"'//TRIM(Surface(ThisSurf)%Name)//'",'// &
                              ' Max "out of line"='//TRIM(TrimSigDigits(OutOfLine,5))//' at Vertex # '//  &
                              TRIM(TrimSigDigits(LastVertexInError)))
       ELSE
         CALL ShowWarningError(RoutineName//'Possible non-planar surface:"'//TRIM(Surface(ThisSurf)%Name)//'",'// &
                              ' Max "out of line"='//TRIM(TrimSigDigits(OutOfLine,5))//' at Vertex # '//  &
                              TRIM(TrimSigDigits(LastVertexInError)))
       ENDIF
!       ErrorInSurface=.true.
     ENDIF
   ENDIF

   IF (BaseSurface) THEN
     SurfWorldAz=Surface(ThisSurf)%Azimuth
     SurfTilt=Surface(ThisSurf)%Tilt
     BaseCosAzimuth=COS(SurfWorldAz*DegToRadians)
     BaseSinAzimuth=SIN(SurfWorldAz*DegToRadians)
     BaseCosTilt=COS(SurfTilt*DegToRadians)
     BaseSinTilt=SIN(SurfTilt*DegToRadians)
     DO N=1,Surface(ThisSurf)%Sides
       X(N)=Surface(ThisSurf)%Vertex(N)%X
       Y(N)=Surface(ThisSurf)%Vertex(N)%Y
       Z(N)=Surface(ThisSurf)%Vertex(N)%Z
     ENDDO
     BaseXLLC=Surface(ThisSurf)%Vertex(2)%X
     BaseYLLC=Surface(ThisSurf)%Vertex(2)%Y
     BaseZLLC=Surface(ThisSurf)%Vertex(2)%Z
     TVect=Surface(ThisSurf)%Vertex(3)-Surface(ThisSurf)%Vertex(2)
     ThisWidth=VecLength(TVect)
     TVect=Surface(ThisSurf)%Vertex(2)-Surface(ThisSurf)%Vertex(1)
     ThisHeight=VecLength(TVect)
     Surface(ThisSurf)%Width=ThisWidth
     Surface(ThisSurf)%Height=ThisHeight ! For a horizontal surface this is actually length!
     IF(Surface(ThisSurf)%Sides==3) Surface(ThisSurf)%Shape = Triangle
     IF(Surface(ThisSurf)%Sides==4) THEN
       Diagonal1 = VecLength(Surface(ThisSurf)%Vertex(1)-Surface(ThisSurf)%Vertex(3))
       Diagonal2 = VecLength(Surface(ThisSurf)%Vertex(2)-Surface(ThisSurf)%Vertex(4))
       ! Test for rectangularity
       IF(ABS(Diagonal1-Diagonal2) < 0.020d0) THEN
         Surface(ThisSurf)%Shape = Rectangle
       ELSE
         Surface(ThisSurf)%Shape = Quadrilateral
       END IF
     END IF
     IF (Surface(ThisSurf)%Sides >4) THEN
       Surface(ThisSurf)%Shape = Polygonal
       if (abs(thisheight*thiswidth-surface(thissurf)%grossarea) > .001d0) then
         surface(thissurf)%width=sqrt(surface(thissurf)%grossarea)
         surface(thissurf)%height=surface(thissurf)%width
         thiswidth=surface(thissurf)%width
         thisheight=surface(thissurf)%height
       endif
     ENDIF

   ELSE   ! It's a subsurface to previous basesurface in this set of calls

     ThisSurfAz=Surface(ThisSurf)%Azimuth
     ThisSurfTilt=Surface(ThisSurf)%Tilt

     IF (HeatTransSurf) then

       IF(Surface(ThisSurf)%Sides == 4) THEN
          ThisShape=RectangularDoorWindow
       ELSE IF(Surface(ThisSurf)%Sides == 3 .AND. Surface(ThisSurf)%Class == SurfaceClass_Window) THEN
          ThisShape=TriangularWindow
       ELSE IF(Surface(ThisSurf)%Sides == 3 .AND. Surface(ThisSurf)%Class == SurfaceClass_Door) THEN
          ThisShape=TriangularDoor
       END IF

     ELSE    !  this is a shadowing subsurface

       IF (ABS(Surface(Surface(ThisSurf)%Basesurf)%Tilt-ThisSurfTilt) <= .01d0) then
         ! left or right fin
         IF (ThisSurfAz < 0.0d0) ThisSurfAz=ThisSurfAz+360.d0
         IF (ThisSurfAz > Surface(Surface(ThisSurf)%BaseSurf)%Azimuth) then
           ThisShape=RectangularLeftFin
         ELSE
           ThisShape=RectangularRightFin
         ENDIF
       ELSE
         ThisShape=RectangularOverhang
       ENDIF

     ENDIF

     ! Setting relative coordinates for shadowing calculations for subsurfaces
     SELECT CASE (ThisShape)

     CASE (RectangularDoorWindow) ! Rectangular heat transfer subsurface

       CALL PlaneEquation(Surface(Surface(ThisSurf)%BaseSurf)%Vertex,Surface(Surface(ThisSurf)%BaseSurf)%Sides,BasePlane,SError)
       IF (SError) THEN
         CALL ShowSevereError(RoutineName//'Degenerate surface (likely two vertices equal):"'//TRIM(Surface(ThisSurf)%Name)//'".')
         ErrorInSurface=.true.
       ENDIF
       ThisReveal=-Pt2Plane(Surface(ThisSurf)%Vertex(2),BasePlane)
       IF (ABS(ThisReveal) < .0002d0) ThisReveal=0.0d0
       Surface(ThisSurf)%Reveal=ThisReveal
       Xp=Surface(ThisSurf)%Vertex(2)%x-BaseXLLC
       Yp=Surface(ThisSurf)%Vertex(2)%y-BaseYLLC
       Zp=Surface(ThisSurf)%Vertex(2)%z-BaseZLLC
       XLLC=-Xp*BaseCosAzimuth+Yp*BaseSinAzimuth
       YLLC=-Xp*BaseSinAzimuth*BaseCosTilt-Yp*BaseCosAzimuth*BaseCosTilt+Zp*BaseSinTilt
       ZLLC= Xp*BaseSinAzimuth*BaseSinTilt+Yp*BaseCosAzimuth*BaseSinTilt+Zp*BaseCosTilt
       TVect=Surface(ThisSurf)%Vertex(3)-Surface(ThisSurf)%Vertex(2)
       ThisWidth=VecLength(TVect)
       TVect=Surface(ThisSurf)%Vertex(2)-Surface(ThisSurf)%Vertex(1)
       ThisHeight=VecLength(TVect)
       Surface(ThisSurf)%Width=ThisWidth
       Surface(ThisSurf)%Height=ThisHeight
       Diagonal1 = VecLength(Surface(ThisSurf)%Vertex(1)-Surface(ThisSurf)%Vertex(3))
       Diagonal2 = VecLength(Surface(ThisSurf)%Vertex(2)-Surface(ThisSurf)%Vertex(4))

       ! Test for rectangularity
       IF(ABS(Diagonal1-Diagonal2) > 0.020d0) THEN
         CALL ShowSevereError(RoutineName//'Suspected 4-sided but non-rectangular Window, Door or GlassDoor:')
         CALL ShowContinueError('Surface='//TRIM(Surface(ThisSurf)%Name) &
                     //', Diagonal1='//TRIM(TrimSigDigits(Diagonal1,3))//', Diagonal2='//TRIM(TrimSigDigits(Diagonal2,3)))
         ErrorInSurface=.true.
       ENDIF

       X(1) = XLLC
       X(2) = XLLC
       X(3) = XLLC + Surface(ThisSurf)%Width
       X(4) = XLLC + Surface(ThisSurf)%Width
       Y(1) = YLLC + Surface(ThisSurf)%Height
       Y(4) = YLLC + Surface(ThisSurf)%Height
       Y(2) = YLLC
       Y(3) = YLLC
       Z(1) = ZLLC
       Z(2) = ZLLC
       Z(3) = ZLLC
       Z(4) = ZLLC

       IF(Surface(ThisSurf)%Class == SurfaceClass_Window .AND. &
          Surface(ThisSurf)%ExtBoundCond == ExternalEnvironment .AND. &
          Surface(ThisSurf)%FrameDivider > 0) THEN
         FrDivNum = Surface(ThisSurf)%FrameDivider
         ! Set flag for calculating beam solar reflection from outside and/or inside window reveal
         IF((Surface(ThisSurf)%Reveal > 0.0d0 .AND. FrameDivider(FrDivNum)%OutsideRevealSolAbs > 0.0d0) .OR. &
            (FrameDivider(FrDivNum)%InsideSillDepth > 0.0d0 .AND. FrameDivider(FrDivNum)%InsideSillSolAbs > 0.0d0) .OR. &
            (FrameDivider(FrDivNum)%InsideReveal > 0.0d0 .AND. FrameDivider(FrDivNum)%InsideRevealSolAbs > 0.0d0)) &
           CalcWindowRevealReflection = .TRUE.

         ! For exterior window with frame, subtract frame area from base surface
         ! (only rectangular windows are allowed to have a frame and/or divider;
         ! Surface(ThisSurf)%FrameDivider will be 0 for triangular windows)
         FrWidth = FrameDivider(FrDivNum)%FrameWidth
         IF(FrWidth > 0.0d0) THEN
           FrArea = (Surface(ThisSurf)%Height + 2.0d0*FrWidth)*(Surface(ThisSurf)%Width + 2.0d0*FrWidth) &
                        - Surface(ThisSurf)%Area/Surface(ThisSurf)%Multiplier
           SurfaceWindow(ThisSurf)%FrameArea = FrArea * Surface(ThisSurf)%Multiplier
           IF((Surface(Surface(ThisSurf)%BaseSurf)%Area - SurfaceWindow(ThisSurf)%FrameArea) <= 0.0d0) THEN
             CALL ShowSevereError(RoutineName//'Base Surface="'//TRIM(Surface(Surface(ThisSurf)%BaseSurf)%Name)//'", ')
             CALL ShowContinueError('Window Surface="'//trim(Surface(ThisSurf)%Name)//  &
                '" area (with frame) is too large to fit on the surface.')
             CALL ShowContinueError('Base surface area (-windows and doors)=['//  &
                trim(TrimSigDigits(Surface(Surface(ThisSurf)%BaseSurf)%Area,2))//  &
                '] m2, frame area=['//trim(TrimSigDigits(SurfaceWindow(ThisSurf)%FrameArea,2))//'] m2.')
             ErrorInSurface=.true.
           ENDIF
           Surface(Surface(ThisSurf)%BaseSurf)%Area =  &
               Surface(Surface(ThisSurf)%BaseSurf)%Area - SurfaceWindow(ThisSurf)%FrameArea
         END IF
       ! If exterior window has divider, subtract divider area to get glazed area
         DivWidth = FrameDivider(Surface(ThisSurf)%FrameDivider)%DividerWidth
         IF(DivWidth > 0.0d0 .and. .not. ErrorInSurface) THEN
           DivArea = DivWidth * &
             (FrameDivider(FrDivNum)%HorDividers * Surface(ThisSurf)%Width + &
              FrameDivider(FrDivNum)%VertDividers * Surface(ThisSurf)%Height - &
              FrameDivider(FrDivNum)%HorDividers * FrameDivider(FrDivNum)%VertDividers * DivWidth)
           SurfaceWindow(ThisSurf)%DividerArea = DivArea * Surface(ThisSurf)%Multiplier
           IF((Surface(ThisSurf)%Area - SurfaceWindow(ThisSurf)%DividerArea) <= 0.0d0) THEN
             CALL ShowSevereError(RoutineName//'Divider area exceeds glazed opening for window '&
                                 //TRIM(Surface(ThisSurf)%Name))
             CALL ShowContinueError('Window surface area=['//  &
                trim(TrimSigDigits(Surface(ThisSurf)%Area,2))//  &
                '] m2, divider area=['//trim(TrimSigDigits(SurfaceWindow(ThisSurf)%DividerArea,2))//'] m2.')
             ErrorInSurface=.true.
           ENDIF
           Surface(ThisSurf)%Area = Surface(ThisSurf)%Area - SurfaceWindow(ThisSurf)%DividerArea  ! Glazed area
           IF (DivArea <= 0.0d0) THEN
             CALL ShowWarningError(RoutineName//'Calculated Divider Area <= 0.0 for Window='//  &
                TRIM(Surface(ThisSurf)%Name))
             IF (FrameDivider(FrDivNum)%HorDividers == 0) THEN
               CALL ShowContinueError('..Number of Horizontal Dividers = 0.')
             ENDIF
             IF (FrameDivider(FrDivNum)%VertDividers == 0) THEN
               CALL ShowContinueError('..Number of Vertical Dividers = 0.')
             ENDIF
           ELSE
             SurfaceWindow(ThisSurf)%GlazedFrac = Surface(ThisSurf)%Area/(Surface(ThisSurf)%Area +  &
                                 SurfaceWindow(ThisSurf)%DividerArea)
             ! Correction factor for portion of divider subject to divider projection correction
             DivFrac = (1.0d0-FrameDivider(FrDivNum)%HorDividers * &
               FrameDivider(FrDivNum)%VertDividers * DivWidth**2 / DivArea)
             SurfaceWindow(ThisSurf)%ProjCorrDivOut = DivFrac * &
               FrameDivider(FrDivNum)%DividerProjectionOut/DivWidth
             SurfaceWindow(ThisSurf)%ProjCorrDivIn = DivFrac * &
               FrameDivider(FrDivNum)%DividerProjectionIn/DivWidth
             ! Correction factor for portion of frame subject to frame projection correction
             IF(FrWidth > 0.0d0) THEN
               SurfaceWindow(ThisSurf)%ProjCorrFrOut = (FrameDivider(FrDivNum)%FrameProjectionOut/FrWidth)* &
                   (ThisHeight+ThisWidth-(FrameDivider(FrDivNum)%HorDividers + FrameDivider(FrDivNum)%VertDividers)* &
                  DivWidth)/(ThisHeight+ThisWidth+2*FrWidth)
               SurfaceWindow(ThisSurf)%ProjCorrFrIn = (FrameDivider(FrDivNum)%FrameProjectionIn/FrWidth)* &
                   (ThisHeight+ThisWidth-(FrameDivider(FrDivNum)%HorDividers + FrameDivider(FrDivNum)%VertDividers)* &
                   DivWidth)/(ThisHeight+ThisWidth+2*FrWidth)

             END IF
           END IF
         END IF
       END IF

     CASE (TriangularWindow,TriangularDoor)

       CALL PlaneEquation(Surface(Surface(ThisSurf)%BaseSurf)%Vertex,Surface(Surface(ThisSurf)%BaseSurf)%Sides,BasePlane,SError)
       IF (SError) THEN
         CALL ShowSevereError(RoutineName//'Degenerate surface (likely two vertices equal):"'//TRIM(Surface(ThisSurf)%Name)//'".')
         ErrorInSurface=.true.
       ENDIF
       ThisReveal=-Pt2Plane(Surface(ThisSurf)%Vertex(2),BasePlane)
       IF (ABS(ThisReveal) < .0002d0) ThisReveal=0.0d0
       Surface(ThisSurf)%Reveal=ThisReveal
       Xp=Surface(ThisSurf)%Vertex(2)%x-BaseXLLC
       Yp=Surface(ThisSurf)%Vertex(2)%y-BaseYLLC
       Zp=Surface(ThisSurf)%Vertex(2)%z-BaseZLLC
       X(2)=-Xp*BaseCosAzimuth+Yp*BaseSinAzimuth
       Y(2)=-Xp*BaseSinAzimuth*BaseCosTilt-Yp*BaseCosAzimuth*BaseCosTilt+Zp*BaseSinTilt
       Z(2)= Xp*BaseSinAzimuth*BaseSinTilt+Yp*BaseCosAzimuth*BaseSinTilt+Zp*BaseCosTilt
       TVect=Surface(ThisSurf)%Vertex(3)-Surface(ThisSurf)%Vertex(2)
       ThisWidth=VecLength(TVect)
       TVect=Surface(ThisSurf)%Vertex(2)-Surface(ThisSurf)%Vertex(1)
       ThisHeight=VecLength(TVect)
       Surface(ThisSurf)%Width=ThisWidth
       Surface(ThisSurf)%Height=ThisHeight
       ! Effective height and width of a triangular window for use in calc of convective air flow
       ! in gap between glass and shading device when shading device is present
       Surface(ThisSurf)%Height = 4.d0*Surface(ThisSurf)%Area/(3.d0*Surface(ThisSurf)%Width)
       Surface(ThisSurf)%Width  = 0.75d0*Surface(ThisSurf)%Width

       Xp=Surface(ThisSurf)%Vertex(1)%x-BaseXLLC
       Yp=Surface(ThisSurf)%Vertex(1)%y-BaseYLLC
       Zp=Surface(ThisSurf)%Vertex(1)%z-BaseZLLC
       X(1)=-Xp*BaseCosAzimuth+Yp*BaseSinAzimuth
       Y(1)=-Xp*BaseSinAzimuth*BaseCosTilt-Yp*BaseCosAzimuth*BaseCosTilt+Zp*BaseSinTilt
       Z(1)= Xp*BaseSinAzimuth*BaseSinTilt+Yp*BaseCosAzimuth*BaseSinTilt+Zp*BaseCosTilt

       Xp=Surface(ThisSurf)%Vertex(3)%x-BaseXLLC
       Yp=Surface(ThisSurf)%Vertex(3)%y-BaseYLLC
       Zp=Surface(ThisSurf)%Vertex(3)%z-BaseZLLC
       X(3)=-Xp*BaseCosAzimuth+Yp*BaseSinAzimuth
       Y(3)=-Xp*BaseSinAzimuth*BaseCosTilt-Yp*BaseCosAzimuth*BaseCosTilt+Zp*BaseSinTilt
       Z(3)= Xp*BaseSinAzimuth*BaseSinTilt+Yp*BaseCosAzimuth*BaseSinTilt+Zp*BaseCosTilt

     CASE (RectangularOverhang)

       Xp=Surface(ThisSurf)%Vertex(2)%x-BaseXLLC
       Yp=Surface(ThisSurf)%Vertex(2)%y-BaseYLLC
       Zp=Surface(ThisSurf)%Vertex(2)%z-BaseZLLC
       XLLC=-Xp*BaseCosAzimuth+Yp*BaseSinAzimuth
       YLLC=-Xp*BaseSinAzimuth*BaseCosTilt-Yp*BaseCosAzimuth*BaseCosTilt+Zp*BaseSinTilt
       ZLLC= Xp*BaseSinAzimuth*BaseSinTilt+Yp*BaseCosAzimuth*BaseSinTilt+Zp*BaseCosTilt
       TVect=Surface(ThisSurf)%Vertex(3)-Surface(ThisSurf)%Vertex(2)
       ThisWidth=VecLength(TVect)
       TVect=Surface(ThisSurf)%Vertex(2)-Surface(ThisSurf)%Vertex(1)
       ThisHeight=VecLength(TVect)
       Surface(ThisSurf)%Width=ThisWidth
       Surface(ThisSurf)%Height=ThisHeight
       X(1) = XLLC
       X(2) = XLLC
       X(3) = XLLC + Surface(ThisSurf)%Width
       X(4) = XLLC + Surface(ThisSurf)%Width
       Y(1) = YLLC
       Y(2) = YLLC
       Y(3) = YLLC
       Y(4) = YLLC
       Z(1) = Surface(ThisSurf)%Height
       Z(4) = Surface(ThisSurf)%Height
       Z(2) = 0.0d0
       Z(3) = 0.0d0

     CASE (RectangularLeftFin)

       Xp=Surface(ThisSurf)%Vertex(2)%x-BaseXLLC
       Yp=Surface(ThisSurf)%Vertex(2)%y-BaseYLLC
       Zp=Surface(ThisSurf)%Vertex(2)%z-BaseZLLC
       XLLC=-Xp*BaseCosAzimuth+Yp*BaseSinAzimuth
       YLLC=-Xp*BaseSinAzimuth*BaseCosTilt-Yp*BaseCosAzimuth*BaseCosTilt+Zp*BaseSinTilt
       ZLLC= Xp*BaseSinAzimuth*BaseSinTilt+Yp*BaseCosAzimuth*BaseSinTilt+Zp*BaseCosTilt
       TVect=Surface(ThisSurf)%Vertex(3)-Surface(ThisSurf)%Vertex(2)
       ThisWidth=VecLength(TVect)
       TVect=Surface(ThisSurf)%Vertex(2)-Surface(ThisSurf)%Vertex(1)
       ThisHeight=VecLength(TVect)
       Surface(ThisSurf)%Width=ThisWidth
       Surface(ThisSurf)%Height=ThisHeight
       X(1) = XLLC
       X(2) = XLLC
       X(3) = XLLC
       X(4) = XLLC
       Y(1) = YLLC
       Y(2) = YLLC
       Y(3) = YLLC + Surface(ThisSurf)%Width
       Y(4) = YLLC + Surface(ThisSurf)%Width
       Z(1) = Surface(ThisSurf)%Height
       Z(4) = Surface(ThisSurf)%Height
       Z(2) = 0.0d0
       Z(3) = 0.0d0

     CASE (RectangularRightFin)

       Xp=Surface(ThisSurf)%Vertex(2)%x-BaseXLLC
       Yp=Surface(ThisSurf)%Vertex(2)%y-BaseYLLC
       Zp=Surface(ThisSurf)%Vertex(2)%z-BaseZLLC
       XLLC=-Xp*BaseCosAzimuth+Yp*BaseSinAzimuth
       YLLC=-Xp*BaseSinAzimuth*BaseCosTilt-Yp*BaseCosAzimuth*BaseCosTilt+Zp*BaseSinTilt
       ZLLC= Xp*BaseSinAzimuth*BaseSinTilt+Yp*BaseCosAzimuth*BaseSinTilt+Zp*BaseCosTilt
       TVect=Surface(ThisSurf)%Vertex(3)-Surface(ThisSurf)%Vertex(2)
       ThisWidth=VecLength(TVect)
       TVect=Surface(ThisSurf)%Vertex(2)-Surface(ThisSurf)%Vertex(1)
       ThisHeight=VecLength(TVect)
       Surface(ThisSurf)%Width=ThisWidth
       Surface(ThisSurf)%Height=ThisHeight
       X(1) = XLLC
       X(2) = XLLC
       X(3) = XLLC
       X(4) = XLLC
       Y(1) = YLLC + Surface(ThisSurf)%Width
       Y(2) = YLLC + Surface(ThisSurf)%Width
       Y(3) = YLLC
       Y(4) = YLLC
       Z(1) = Surface(ThisSurf)%Height
       Z(4) = Surface(ThisSurf)%Height
       Z(2) = 0.0d0
       Z(3) = 0.0d0

     CASE DEFAULT
       ! Error Condition
       CALL ShowSevereError(RoutineName//'Incorrect surface shape number.',OutputFileStandard)
       CALL ShowContinueError('Please notify EnergyPlus support of this error and send input file.')
       ErrorInSurface=.true.

     END SELECT

     DO N = 1, Surface(ThisSurf)%Sides
      ! if less than 1/10 inch
       X(N)=ANINT(10000.d0*X(N),r64)/10000.d0
       IF (ABS(X(N)) < .0025d0) X(N)=0.0d0
       Y(N)=ANINT(10000.d0*Y(N),r64)/10000.d0
       IF (ABS(Y(N)) < .0025d0) Y(N)=0.0d0
       Z(N)=ANINT(10000.d0*Z(N),r64)/10000.d0
       IF (ABS(Z(N)) < .0025d0) Z(N)=0.0d0
     ENDDO

     Surface(ThisSurf)%Shape=ThisShape

   ENDIF  ! End of check if ThisSurf is a base surface

   IF (ErrorInSurface) THEN
     ErrorsFound=.true.
     RETURN
   ENDIF

    ! Transfer to XV,YV,ZV arrays

   ShadeV(ThisSurf)%NVert=Surface(ThisSurf)%Sides
   ALLOCATE(ShadeV(ThisSurf)%XV(Surface(ThisSurf)%Sides))
   ALLOCATE(ShadeV(ThisSurf)%YV(Surface(ThisSurf)%Sides))
   ALLOCATE(ShadeV(ThisSurf)%ZV(Surface(ThisSurf)%Sides))

   DO N = 1, Surface(ThisSurf)%Sides
    ! if less than 1/10 inch
     ShadeV(ThisSurf)%XV(N) = X(N)
     ShadeV(ThisSurf)%YV(N) = Y(N)
     ShadeV(ThisSurf)%ZV(N) = Z(N)
   END DO

          ! Process Surfaces According to Type of Coordinate Origin.
   IF (BaseSurface) THEN

          ! General Surfaces:
     CALL CalcCoordinateTransformation(ThisSurf,CoordinateTransVector) !X00,Y00,Z00,X,Y,Z,A)    ! Compute Coordinate Transformation

          ! RECORD DIRECTION COSINES.
     IF (HeatTransSurf) THEN ! This is a general surface but not detached shading surface

          ! RECORD COORDINATE TRANSFORMATION FOR BASE SURFACES.
       X0(ThisBaseSurface) = CoordinateTransVector%x
       Y0(ThisBaseSurface) = CoordinateTransVector%y
       Z0(ThisBaseSurface) = CoordinateTransVector%z

          ! COMPUTE INVERSE TRANSFORMATION.
       X1     = X(2) - CoordinateTransVector%x
       Y1     = Y(2) - CoordinateTransVector%y
       Z1     = Z(2) - CoordinateTransVector%z
       XSHIFT = Surface(ThisBaseSurface)%lcsx%x*X1 + Surface(ThisBaseSurface)%lcsx%y*Y1 + Surface(ThisBaseSurface)%lcsx%z*Z1
       YSHIFT = Surface(ThisBaseSurface)%lcsy%x*X1 + Surface(ThisBaseSurface)%lcsy%y*Y1 + Surface(ThisBaseSurface)%lcsy%z*Z1

     ENDIF

          ! SUBSURFACES: (Surface(ThisSurf)%BaseSurf /= ThisSurf)
   ELSE
          ! WINDOWS OR DOORS:

          ! SHIFT RELATIVE COORDINATES FROM LOWER LEFT CORNER TO ORIGIN DEFINED
          ! BY CTRAN AND SET DIRECTION COSINES SAME AS BASE SURFACE.

     DO N = 1, Surface(ThisSurf)%Sides
       ShadeV(ThisSurf)%XV(N) = ShadeV(ThisSurf)%XV(N) + XSHIFT
       ShadeV(ThisSurf)%YV(N) = ShadeV(ThisSurf)%YV(N) + YSHIFT
     ENDDO

   ENDIF

   IF (ErrorInSurface) THEN
     ErrorsFound=.true.
   ENDIF

  RETURN

END SUBROUTINE ProcessSurfaceVertices

SUBROUTINE CalcCoordinateTransformation(SurfNum,CompCoordTranslVector)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         George Walton, BLAST
          !       DATE WRITTEN   August 1976
          !       MODIFIED       LKL, May 2004 -- >4 sided polygons
          !       RE-ENGINEERED  Yes

          ! PURPOSE OF THIS SUBROUTINE:
          ! This subroutine develops a coordinate transformation such that the X-axis goes
          ! through points 2 and 3 and the Y-axis goes through point 1
          ! of a plane figure in 3-d space.

          ! METHODOLOGY EMPLOYED:
          ! na

          ! REFERENCES:
          ! 'NECAP' - NASA'S Energy-Cost Analysis Program

          ! USE STATEMENTS:
  USE Vectors

  IMPLICIT NONE    ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
  INTEGER, INTENT(IN)           :: SurfNum                 ! Surface Number
  TYPE(vector) :: CompCoordTranslVector  ! Coordinate Translation Vector

          ! SUBROUTINE PARAMETER DEFINITIONS:
  CHARACTER(len=*), PARAMETER :: ErrFmt="(' (',F8.3,',',F8.3,',',F8.3,')')"

          ! INTERFACE BLOCK SPECIFICATIONS
          ! na

          ! DERIVED TYPE DEFINITIONS
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
  INTEGER I               ! Loop Control
  REAL(r64) GAMMA              ! Intermediate Result
  REAL(r64) DotSelfX23
  CHARACTER(len=132) :: ErrLineOut=Blank ! Character string for producing error messages
  TYPE (vector) :: x21
  TYPE (vector) :: x23

          ! Determine Components of the Coordinate Translation Vector.

  x21=Surface(SurfNum)%Vertex(2)-Surface(SurfNum)%Vertex(1)
  x23=Surface(SurfNum)%Vertex(2)-Surface(SurfNum)%Vertex(3)

  DotSelfX23=(x23 .dot. x23)

  IF (ABS(DotSelfX23) <= .1d-6) THEN
    CALL ShowSevereError('CalcCoordinateTransformation: Invalid dot product, surface="'//  &
                         TRIM(Surface(SurfNum)%Name)//'":')
    DO I=1,Surface(SurfNum)%Sides
      WRITE(ErrLineOut,ErrFmt) Surface(SurfNum)%Vertex(I)
      CALL ShowContinueError(ErrLineOut)
    ENDDO
    CALL ShowFatalError('CalcCoordinateTransformation: Program terminates due to preceding condition.',OutputFileStandard)
    RETURN
  END IF

  Gamma = (x21 .dot. x23) / (x23 .dot. x23)

  CompCoordTranslVector = Surface(SurfNum)%Vertex(2) + Gamma * (Surface(SurfNum)%Vertex(3)-Surface(SurfNum)%Vertex(2))

  RETURN

END SUBROUTINE CalcCoordinateTransformation

SUBROUTINE CreateShadedWindowConstruction(SurfNum,WSCptr,ShDevNum)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Fred Winkelmann
          !       DATE WRITTEN   Nov 2001
          !       MODIFIED       na
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! Creates a shaded window construction for windows whose WindowShadingControl
          ! has a shading device specified instead of a shaded construction

          ! METHODOLOGY EMPLOYED:na

          ! REFERENCES:na

          ! USE STATEMENTS:
  USE InputProcessor, ONLY: FindItemInList

  IMPLICIT NONE    ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
  INTEGER, INTENT(IN)       :: SurfNum           ! Surface number
  INTEGER, INTENT(IN)       :: WSCptr            ! Pointer to WindowShadingControl for SurfNum
  INTEGER, INTENT(IN)       :: ShDevNum          ! Shading device material number for WSCptr

          ! SUBROUTINE PARAMETER DEFINITIONS:na
          ! INTERFACE BLOCK SPECIFICATIONS;na
          ! DERIVED TYPE DEFINITIONS:na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
  INTEGER :: ConstrNum                       ! Number of unshaded construction
  INTEGER :: ConstrNewSh                     ! Number of shaded construction that is created
  CHARACTER(len=MaxNameLength) :: ShDevName  ! Shading device material name
  CHARACTER(len=MaxNameLength) :: ConstrName ! Unshaded construction name
  CHARACTER(len=MaxNameLength) :: ConstrNameSh ! Shaded construction name
  INTEGER :: TotLayersOld                    ! Total layers in old (unshaded) construction
  INTEGER :: TotLayersNew                    ! Total layers in new (shaded) construction
!  INTEGER :: loop                            ! DO loop index

ShDevName = Material(ShDevNum)%Name
ConstrNum = SurfaceTmp(SurfNum)%Construction
ConstrName= Construct(ConstrNum)%Name
IF(WindowShadingControl(WSCptr)%ShadingType==WSC_ST_InteriorShade.OR. &
   WindowShadingControl(WSCptr)%ShadingType==WSC_ST_InteriorBlind) THEN
  ConstrNameSh = TRIM(ConstrName)//':'//TRIM(ShDevName)//':'//'INT'
ELSE
  ConstrNameSh = TRIM(ConstrName)//':'//TRIM(ShDevName)//':'//'EXT'
END IF

! If this construction name already exists, set the surface's shaded construction number to it

ConstrNewSh = FindIteminList(ConstrNameSh,Construct%Name,TotConstructs)

IF(ConstrNewSh > 0) THEN
  SurfaceTmp(SurfNum)%ShadedConstruction = ConstrNewSh
ELSE

  ! Create new construction

  ConstrNewSh = TotConstructs + 1
  SurfaceTmp(SurfNum)%ShadedConstruction = ConstrNewSh
  ALLOCATE(ConstructSave(TotConstructs))
  ALLOCATE(NominalRSave(TotConstructs))
  ALLOCATE(NominalUSave(TotConstructs))
  ConstructSave(1:TotConstructs) = Construct(1:TotConstructs)
  NominalRSave(1:TotConstructs) = NominalRforNominalUCalculation(1:TotConstructs)
  NominalUSave(1:TotConstructs) = NominalU(1:TotConstructs)
  DEALLOCATE(Construct)
  DEALLOCATE(NominalRforNominalUCalculation)
  DEALLOCATE(NominalU)
  TotConstructs = ConstrNewSh
  ALLOCATE(Construct(TotConstructs))
  ALLOCATE(NominalRforNominalUCalculation(TotConstructs))
  ALLOCATE(NominalU(TotConstructs))
  NominalRforNominalUCalculation=0.0d0
  NominalU=0.0d0
  Construct(1:TotConstructs-1) = ConstructSave(1:TotConstructs-1)
  NominalRforNominalUCalculation(1:TotConstructs-1) = NominalRSave(1:TotConstructs-1)
  NominalU(1:TotConstructs-1) = NominalUSave(1:TotConstructs-1)
  DEALLOCATE(ConstructSave)
  DEALLOCATE(NominalRSave)
  DEALLOCATE(NominalUSave)

  TotLayersOld = Construct(ConstrNum)%TotLayers
  TotLayersNew = TotLayersOld + 1

  Construct(ConstrNewSh)%LayerPoint = 0

  IF(WindowShadingControl(WSCptr)%ShadingType==WSC_ST_InteriorShade.OR. &
     WindowShadingControl(WSCptr)%ShadingType==WSC_ST_InteriorBlind) THEN
    ! Interior shading device
    Construct(ConstrNewSh)%LayerPoint(1:TotLayersOld) = Construct(ConstrNum)%LayerPoint(1:TotLayersOld)
    Construct(ConstrNewSh)%LayerPoint(TotLayersNew)   = ShDevNum
    Construct(ConstrNewSh)%InsideAbsorpSolar    = Material(ShDevNum)%AbsorpSolar
    Construct(ConstrNewSh)%OutsideAbsorpSolar   = Material(Construct(ConstrNewSh)%LayerPoint(1))%AbsorpSolar
    Construct(ConstrNewSh)%OutsideAbsorpThermal = Material(Construct(ConstrNewSh)%LayerPoint(1))%AbsorpThermalFront
  ELSE
    ! Exterior shading device
    Construct(ConstrNewSh)%LayerPoint(1) = ShDevNum
    Construct(ConstrNewSh)%LayerPoint(2:TotLayersNew) = Construct(ConstrNum)%LayerPoint(1:TotLayersOld)
    Construct(ConstrNewSh)%InsideAbsorpSolar    = &
      Material(Construct(ConstrNewSh)%LayerPoint(TotLayersNew))%AbsorpSolar
    Construct(ConstrNewSh)%OutsideAbsorpSolar   = Material(ShDevNum)%AbsorpSolar
    Construct(ConstrNewSh)%OutsideAbsorpThermal = Material(ShDevNum)%AbsorpThermalFront
  END IF
  ! The following InsideAbsorpThermal applies only to inside glass; it is corrected
  !  later in InitGlassOpticalCalculations if construction has inside shade or blind.
  Construct(ConstrNewSh)%InsideAbsorpThermal = &
        Material(Construct(ConstrNum)%LayerPoint(TotLayersOld))%AbsorpThermalBack
  Construct(ConstrNewSh)%OutSideRoughness     = VerySmooth
  Construct(ConstrNewSh)%DayltPropPtr        = 0
  Construct(ConstrNewSh)%CTFCross            = 0.0D0
  Construct(ConstrNewSh)%CTFFlux             = 0.0D0
  Construct(ConstrNewSh)%CTFInside           = 0.0D0
  Construct(ConstrNewSh)%CTFOutside          = 0.0D0
  Construct(ConstrNewSh)%CTFSourceIn         = 0.0D0
  Construct(ConstrNewSh)%CTFSourceOut        = 0.0D0
  Construct(ConstrNewSh)%CTFTimeStep         = 0.0D0
  Construct(ConstrNewSh)%CTFTSourceOut       = 0.0D0
  Construct(ConstrNewSh)%CTFTSourceIn        = 0.0D0
  Construct(ConstrNewSh)%CTFTSourceQ         = 0.0D0
  Construct(ConstrNewSh)%CTFTUserOut         = 0.0D0
  Construct(ConstrNewSh)%CTFTUserIn          = 0.0D0
  Construct(ConstrNewSh)%CTFTUserSource      = 0.0D0
  Construct(ConstrNewSh)%NumHistories        = 0
  Construct(ConstrNewSh)%NumCTFTerms         = 0
  Construct(ConstrNewSh)%UValue              = 0.0d0
  Construct(ConstrNewSh)%SourceSinkPresent   = .FALSE.
  Construct(ConstrNewSh)%SolutionDimensions  = 0
  Construct(ConstrNewSh)%SourceAfterLayer    = 0
  Construct(ConstrNewSh)%TempAfterLayer      = 0
  Construct(ConstrNewSh)%ThicknessPerpend    = 0.0d0
  Construct(ConstrNewSh)%AbsDiff             = 0.0d0
  Construct(ConstrNewSh)%AbsDiffBack         = 0.0d0
  Construct(ConstrNewSh)%AbsDiffShade        = 0.0d0
  Construct(ConstrNewSh)%AbsDiffBackShade    = 0.0d0
  Construct(ConstrNewSh)%ShadeAbsorpThermal  = 0.0d0
  Construct(ConstrNewSh)%AbsBeamCoef         = 0.0d0
  Construct(ConstrNewSh)%AbsBeamBackCoef     = 0.0d0
  Construct(ConstrNewSh)%AbsBeamShadeCoef    = 0.0d0
  Construct(ConstrNewSh)%TransDiff           = 0.0d0
  Construct(ConstrNewSh)%TransDiffVis        = 0.0d0
  Construct(ConstrNewSh)%ReflectSolDiffBack  = 0.0d0
  Construct(ConstrNewSh)%ReflectSolDiffFront = 0.0d0
  Construct(ConstrNewSh)%ReflectVisDiffBack  = 0.0d0
  Construct(ConstrNewSh)%ReflectVisDiffFront = 0.0d0
  Construct(ConstrNewSh)%TransSolBeamCoef    = 0.0d0
  Construct(ConstrNewSh)%TransVisBeamCoef    = 0.0d0
  Construct(ConstrNewSh)%ReflSolBeamFrontCoef= 0.0d0
  Construct(ConstrNewSh)%ReflSolBeamBackCoef = 0.0d0
  Construct(ConstrNewSh)%W5FrameDivider      = 0
  Construct(ConstrNewSh)%FromWindow5DataFile = .false.

  Construct(ConstrNewSh)%Name = ConstrNameSh
  Construct(ConstrNewSh)%TotLayers = TotLayersNew
  Construct(ConstrNewSh)%TotSolidLayers = Construct(ConstrNum)%TotSolidLayers + 1
  Construct(ConstrNewSh)%TotGlassLayers = Construct(ConstrNum)%TotGlassLayers
  Construct(ConstrNewSh)%TypeIsWindow = .true.
  Construct(ConstrNewSh)%IsUsed       = .true.

END IF

RETURN
END SUBROUTINE CreateShadedWindowConstruction

SUBROUTINE CreateStormWindowConstructions

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Fred Winkelmann
          !       DATE WRITTEN   Jan 2004
          !       MODIFIED       na
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! For windows with an associated StormWindow object, creates a construction
          ! consisting of the base construction plus a storm window and air gap on the outside.
          ! If the window has an interior or between-glass shade/blind, also creates a
          ! construction consisting of the storm window added to the shaded construction.

          ! METHODOLOGY EMPLOYED:na
          ! REFERENCES:na

          ! USE STATEMENTS:
  USE InputProcessor, ONLY: FindItemInList

  IMPLICIT NONE    ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
          ! SUBROUTINE PARAMETER DEFINITIONS:na
          ! INTERFACE BLOCK SPECIFICATIONS;na
          ! DERIVED TYPE DEFINITIONS:na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
  INTEGER :: SurfNum               ! Surface number
  INTEGER :: StormWinNum           ! Number of StormWindow object
  INTEGER :: ConstrNum             ! Number of unshaded construction
  INTEGER :: ConstrNumSh           ! Number of shaded construction
  INTEGER :: ConstrOld             ! Number of old construction (unshaded or shaded)
  INTEGER :: ConstrNewSt           ! Number of unshaded storm window construction that is created
  INTEGER :: ConstrNewStSh         ! Number of shaded storm window construction that is created
  INTEGER :: ConstrNew             ! Number of new construction with storm window (unshaded or shaded)
  INTEGER :: MatNewStAir           ! Number of created air layer material
  CHARACTER(len=MaxNameLength) :: ConstrName   ! Name of original unshaded window construction
  CHARACTER(len=MaxNameLength) :: ConstrNameSh ! Name of original shaded window construction
  CHARACTER(len=MaxNameLength) :: ConstrNameSt ! Name of unshaded construction with storm window
  CHARACTER(len=MaxNameLength) :: ConstrNameStsh ! Name of shaded construction with storm window
  CHARACTER(len=MaxNameLength) :: MatNameStAir ! Name of created air layer material
  INTEGER :: StormWinMatNum        ! Material number of storm window glass layer
  INTEGER :: IntDistance           ! Thickness of air gap between storm window and rest of window (mm)
  CHARACTER(len=20) :: ChrIntDistance ! Character representation of IntDistance
  CHARACTER(len=29) :: ChrNum      ! Character representation of storm window number
  INTEGER :: TotLayers             ! Total layers in a construction
  INTEGER :: TotGlassLayers        ! Total glass layers in a construction
  INTEGER :: TotLayersOld          ! Total layers in old (without storm window) construction
  INTEGER :: MatIntSh              ! Material number of interior shade or blind
  INTEGER :: MatBGsh               ! Material number of between-glass shade or blind
  INTEGER :: loop                  ! DO loop index
  LOGICAL :: ShAndSt               ! True if unshaded and shaded window can have a storm window
!  INTEGER :: LenName               ! Name length

CALL DisplayString('Creating Storm Window Constructions')

DO StormWinNum = 1,TotStormWin
  SurfNum = StormWindow(StormWinNum)%BaseWindowNum
  ConstrNum    = Surface(SurfNum)%Construction
  ! Fatal error if base construction has more than three glass layers
  IF(Construct(ConstrNum)%TotGlassLayers > 3) THEN
    CALL ShowFatalError('Window='//TRIM(Surface(SurfNum)%Name) &
         //' has more than 3 glass layers; a storm window cannot be applied.')
  END IF
  ConstrNumSh  = Surface(SurfNum)%ShadedConstruction
  ConstrName   = Construct(ConstrNum)%Name
  StormWinMatNum = StormWindow(StormWinNum)%StormWinMaterialNum
  IntDistance = INT(1000*StormWindow(StormWinNum)%StormWinDistance)
  WRITE(ChrIntDistance,*) IntDistance
  ChrIntDistance = ADJUSTL(ChrIntDistance)
  ! Set ShAndSt, which is true if the window has a shaded construction to which a storm window
  ! can be added. (A storm window can be added if there is an interior shade or blind and up to three
  ! glass layers, or there is a between-glass shade or blind and two glass layers.)
  ShAndSt = .false.
  IF(ConstrNumSh > 0) THEN
    ConstrNameSh = Construct(ConstrNumSh)%Name
    TotLayers = Construct(ConstrNumSh)%TotLayers
    TotGlassLayers = Construct(ConstrNumSh)%TotGlassLayers
    MatIntSh = Construct(ConstrNumSh)%LayerPoint(TotLayers)
    MatBGsh  = 0
    IF(TotLayers == 5) MatBGsh = Construct(ConstrNumSh)%LayerPoint(3)
    IF(TotGlassLayers <= 3 .AND. (Material(MatIntSh)%Group == Shade .OR. &
              Material(MatIntSh)%Group == WindowBlind)) ShAndSt = .true.
    IF(MatBGsh > 0) THEN
      IF(Material(MatBGsh)%Group == Shade .OR. Material(MatBGsh)%Group == WindowBlind) ShAndSt = .true.
    END IF
    IF(.not.ShAndSt) THEN
      CALL ShowContinueError('Window='//TRIM(Surface(SurfNum)%Name) &
         //' has a shaded construction to which a storm window cannot be applied.')
      CALL ShowContinueError('Storm windows can only be applied to shaded constructions that:')
      CALL ShowContinueError('have an interior shade or blind and up to three glass layers, or')
      CALL ShowContinueError('have a between-glass shade or blind and two glass layers.')
      CALL ShowFatalError('EnergyPlus is exiting due to reason stated above.')
    END IF
  END IF

  ! Loop over unshaded (loop=1) and shaded (loop=2) constructions and create new constructions
  ! with storm window and air gap added on outside
  DO loop = 1,2
    IF(loop == 1) THEN
      WRITE(ChrNum,*) StormWinNum
      ChrNum = ADJUSTL(ChrNum)
      ConstrNameSt = 'BARECONSTRUCTIONWITHSTORMWIN:'//TRIM(ChrNum)
      ! If this construction name already exists, set the surface's storm window construction number to it
      ConstrNewSt = FindIteminList(ConstrNameSt,Construct%Name,TotConstructs)
      ConstrNewStSh=0
      IF(ConstrNewSt > 0) Surface(SurfNum)%StormWinConstruction = ConstrNewSt
    ELSE
      IF(.not.ShAndSt) EXIT
      ConstrNameStSh = 'SHADEDCONSTRUCTIONWITHSTORMWIN:'//TRIM(ChrNum)
      ConstrNewStSh = FindIteminList(ConstrNameStSh,Construct%Name,TotConstructs)
      IF(ConstrNewStSh > 0) Surface(SurfNum)%StormWinShadedConstruction = ConstrNewStSh
    END IF

    IF(loop==1 .AND. ConstrNewSt==0) THEN
      ! If necessary, create new material corresponding to the air layer between the storm winddow
      ! and the rest of the window
      MatNameStAir = 'AIR:STORMWIN:'//TRIM(ChrIntDistance)//'MM'
      MatNewStAir = FindItemInList(MatNameStAir,Material%Name,TotMaterials)
      IF(MatNewStAir == 0) THEN
        ! Create new material
        MatNewStAir = TotMaterials + 1
        ALLOCATE(MaterialSave(TotMaterials))
        ALLOCATE(NominalRSave(TotMaterials))
        MaterialSave(1:TotMaterials) = Material(1:TotMaterials)
        NominalRSave(1:TotMaterials) = NominalR(1:TotMaterials)
        DEALLOCATE(Material)
        DEALLOCATE(NominalR)
        TotMaterials = MatNewStAir
        ALLOCATE(Material(TotMaterials))
        ALLOCATE(NominalR(TotMaterials))
        Material(1:TotMaterials-1) = MaterialSave(1:TotMaterials-1)
        NominalR(1:TotMaterials-1) = NominalRSave(1:TotMaterials-1)
        DEALLOCATE(MaterialSave)
        DEALLOCATE(NominalRSave)
        Material(TotMaterials)%Name = MatNameStAir
        Material(TotMaterials)%Group = WindowGas
        Material(TotMaterials)%Roughness = 3
        Material(TotMaterials)%Conductivity = 0.0d0
        Material(TotMaterials)%Density = 0.0d0
        Material(TotMaterials)%IsoMoistCap = 0.0d0
        Material(TotMaterials)%Porosity = 0.0d0
        Material(TotMaterials)%Resistance = 0.0d0
        Material(TotMaterials)%SpecHeat = 0.0d0
        Material(TotMaterials)%ThermGradCoef = 0.0d0
        Material(TotMaterials)%Thickness = StormWindow(StormWinNum)%StormWinDistance
        Material(TotMaterials)%VaporDiffus = 0.0d0
        Material(TotMaterials)%GasType = 0
        Material(TotMaterials)%GasCon = 0.0d0
        Material(TotMaterials)%GasVis = 0.0d0
        Material(TotMaterials)%GasCp = 0.0d0
        Material(TotMaterials)%GasWght = 0.0d0
        Material(TotMaterials)%GasFract = 0.0d0
        Material(TotMaterials)%GasType(1) = 1
        Material(TotMaterials)%GlassSpectralDataPtr = 0
        Material(TotMaterials)%NumberOfGasesInMixture = 1
        Material(TotMaterials)%GasCon(1,1) = 2.873d-3
        Material(TotMaterials)%GasCon(1,2) = 7.760d-5
        Material(TotMaterials)%GasVis(1,1) = 3.723d-6
        Material(TotMaterials)%GasVis(1,2) = 4.940d-8
        Material(TotMaterials)%GasCp(1,1)  = 1002.737d0
        Material(TotMaterials)%GasCp(1,2)  = 1.2324d-2
        Material(TotMaterials)%GasWght(1) = 28.97d0
        Material(TotMaterials)%GasFract(1) = 1.0d0
        Material(TotMaterials)%AbsorpSolar = 0.0d0
        Material(TotMaterials)%AbsorpThermal = 0.0d0
        Material(TotMaterials)%AbsorpVisible = 0.0d0
        Material(TotMaterials)%Trans = 0.0d0
        Material(TotMaterials)%TransVis = 0.0d0
        Material(TotMaterials)%GlassTransDirtFactor = 0.0d0
        Material(TotMaterials)%ReflectShade = 0.0d0
        Material(TotMaterials)%ReflectShadeVis = 0.0d0
        Material(TotMaterials)%AbsorpThermalBack = 0.0d0
        Material(TotMaterials)%AbsorpThermalFront = 0.0d0
        Material(TotMaterials)%ReflectSolBeamBack = 0.0d0
        Material(TotMaterials)%ReflectSolBeamFront = 0.0d0
        Material(TotMaterials)%ReflectSolDiffBack = 0.0d0
        Material(TotMaterials)%ReflectSolDiffFront = 0.0d0
        Material(TotMaterials)%ReflectVisBeamBack = 0.0d0
        Material(TotMaterials)%ReflectVisBeamFront = 0.0d0
        Material(TotMaterials)%ReflectVisDiffBack = 0.0d0
        Material(TotMaterials)%ReflectVisDiffFront = 0.0d0
        Material(TotMaterials)%TransSolBeam = 0.0d0
        Material(TotMaterials)%TransThermal = 0.0d0
        Material(TotMaterials)%TransVisBeam = 0.0d0
        Material(TotMaterials)%BlindDataPtr = 0
        Material(TotMaterials)%WinShadeToGlassDist = 0.0d0
        Material(TotMaterials)%WinShadeTopOpeningMult = 0.0d0
        Material(TotMaterials)%WinShadeBottomOpeningMult = 0.0d0
        Material(TotMaterials)%WinShadeLeftOpeningMult = 0.0d0
        Material(TotMaterials)%WinShadeRightOpeningMult = 0.0d0
        Material(TotMaterials)%WinShadeAirFlowPermeability = 0.0d0
        Material(TotMaterials)%EMPDVALUE = 0.0d0
        Material(TotMaterials)%MoistACoeff = 0.0d0
        Material(TotMaterials)%MoistBCoeff = 0.0d0
        Material(TotMaterials)%MoistCCoeff = 0.0d0
        Material(TotMaterials)%MoistDCoeff = 0.0d0
        Material(TotMaterials)%EMPDaCoeff = 0.0d0
        Material(TotMaterials)%EMPDbCoeff = 0.0d0
        Material(TotMaterials)%EMPDcCoeff = 0.0d0
        Material(TotMaterials)%EMPDdCoeff = 0.0d0
      END IF  ! End of check if new air layer material has to be created
    END IF

    IF((loop==1.AND.ConstrNewSt==0).OR.(loop==2.AND.ConstrNewStSh==0)) THEN
      ! Create new constructions
      ConstrNew = TotConstructs + 1
      IF(loop==1) THEN
        Surface(SurfNum)%StormWinConstruction = ConstrNew
      ELSE
        Surface(SurfNum)%StormWinShadedConstruction = ConstrNew
      END IF
      ALLOCATE(ConstructSave(TotConstructs))
      ALLOCATE(NominalRSave(TotConstructs))
      ALLOCATE(NominalUSave(TotConstructs))
      ConstructSave(1:TotConstructs) = Construct(1:TotConstructs)
      NominalRSave(1:TotConstructs) = NominalRforNominalUCalculation(1:TotConstructs)
      NominalUSave(1:TotConstructs) = NominalU(1:TotConstructs)
      DEALLOCATE(Construct)
      DEALLOCATE(NominalRforNominalUCalculation)
      DEALLOCATE(NominalU)
      TotConstructs = ConstrNew
      ALLOCATE(Construct(TotConstructs))
      ALLOCATE(NominalRforNominalUCalculation(TotConstructs))
      ALLOCATE(NominalU(TotConstructs))
      Construct(1:TotConstructs-1) = ConstructSave(1:TotConstructs-1)
      NominalRforNominalUCalculation(1:TotConstructs-1) = NominalRSave(1:TotConstructs-1)
      NominalU(1:TotConstructs-1) = NominalUSave(1:TotConstructs-1)
      DEALLOCATE(ConstructSave)
      DEALLOCATE(NominalRSave)
      DEALLOCATE(NominalUSave)

      ConstrOld = ConstrNum
      IF(loop==2) ConstrOld = ConstrNumSh
      TotLayersOld = Construct(ConstrOld)%TotLayers
      Construct(ConstrNew)%LayerPoint(1:MaxLayersInConstruct) = 0
      Construct(ConstrNew)%LayerPoint(1) = StormWinMatNum
      Construct(ConstrNew)%LayerPoint(2) = MatNewStAir
      Construct(ConstrNew)%LayerPoint(3:TotLayersOld + 2) = Construct(ConstrOld)%LayerPoint(1:TotLayersOld)
      Construct(ConstrNew)%Name = ConstrNameSt
      IF(loop==2) Construct(ConstrNew)%Name = ConstrNameStSh
      Construct(ConstrNew)%TotLayers = TotLayersOld + 2
      Construct(ConstrNew)%TotSolidLayers = Construct(ConstrOld)%TotSolidLayers + 1
      Construct(ConstrNew)%TotGlassLayers = Construct(ConstrOld)%TotGlassLayers + 1
      Construct(ConstrNew)%TypeIsWindow = .true.
      Construct(ConstrNew)%InsideAbsorpVis      = 0.0d0
      Construct(ConstrNew)%OutsideAbsorpVis     = 0.0d0
      Construct(ConstrNew)%InsideAbsorpSolar    = 0.0d0
      Construct(ConstrNew)%OutsideAbsorpSolar   = 0.0d0
      Construct(ConstrNew)%InsideAbsorpThermal  = Construct(ConstrOld)%InsideAbsorpThermal
      Construct(ConstrNew)%OutsideAbsorpThermal = Material(StormWinMatNum)%AbsorpThermalFront
      Construct(ConstrNew)%OutSideRoughness     = VerySmooth
      Construct(ConstrNew)%DayltPropPtr        = 0
      Construct(ConstrNew)%CTFCross            = 0.0D0
      Construct(ConstrNew)%CTFFlux             = 0.0D0
      Construct(ConstrNew)%CTFInside           = 0.0D0
      Construct(ConstrNew)%CTFOutside          = 0.0D0
      Construct(ConstrNew)%CTFSourceIn         = 0.0D0
      Construct(ConstrNew)%CTFSourceOut        = 0.0D0
      Construct(ConstrNew)%CTFTimeStep         = 0.0D0
      Construct(ConstrNew)%CTFTSourceOut       = 0.0D0
      Construct(ConstrNew)%CTFTSourceIn        = 0.0D0
      Construct(ConstrNew)%CTFTSourceQ         = 0.0D0
      Construct(ConstrNew)%CTFTUserOut         = 0.0D0
      Construct(ConstrNew)%CTFTUserIn          = 0.0D0
      Construct(ConstrNew)%CTFTUserSource      = 0.0D0
      Construct(ConstrNew)%NumHistories        = 0
      Construct(ConstrNew)%NumCTFTerms         = 0
      Construct(ConstrNew)%UValue              = 0.0d0
      Construct(ConstrNew)%SourceSinkPresent   = .false.
      Construct(ConstrNew)%SolutionDimensions  = 0
      Construct(ConstrNew)%SourceAfterLayer    = 0
      Construct(ConstrNew)%TempAfterLayer      = 0
      Construct(ConstrNew)%ThicknessPerpend    = 0.0d0
      Construct(ConstrNew)%AbsDiffIn           = 0.0d0
      Construct(ConstrNew)%AbsDiffOut          = 0.0d0
      Construct(ConstrNew)%AbsDiff             = 0.0d0
      Construct(ConstrNew)%AbsDiffBack         = 0.0d0
      Construct(ConstrNew)%AbsDiffShade        = 0.0d0
      Construct(ConstrNew)%AbsDiffBackShade    = 0.0d0
      Construct(ConstrNew)%ShadeAbsorpThermal  = 0.0d0
      Construct(ConstrNew)%AbsBeamCoef         = 0.0d0
      Construct(ConstrNew)%AbsBeamBackCoef     = 0.0d0
      Construct(ConstrNew)%AbsBeamShadeCoef    = 0.0d0
      Construct(ConstrNew)%TransDiff           = 0.0d0
      Construct(ConstrNew)%TransDiffVis        = 0.0d0
      Construct(ConstrNew)%ReflectSolDiffBack  = 0.0d0
      Construct(ConstrNew)%ReflectSolDiffFront = 0.0d0
      Construct(ConstrNew)%ReflectVisDiffBack  = 0.0d0
      Construct(ConstrNew)%ReflectVisDiffFront = 0.0d0
      Construct(ConstrNew)%TransSolBeamCoef    = 0.0d0
      Construct(ConstrNew)%TransVisBeamCoef    = 0.0d0
      Construct(ConstrNew)%ReflSolBeamFrontCoef= 0.0d0
      Construct(ConstrNew)%ReflSolBeamBackCoef = 0.0d0
      Construct(ConstrNew)%W5FrameDivider      = 0
      Construct(ConstrNew)%FromWindow5DataFile = .false.
      Construct(ConstrNew)%W5FileMullionWidth  = 0.0d0
      Construct(ConstrNew)%W5FileMullionOrientation = 0
      Construct(ConstrNew)%W5FileGlazingSysWidth = 0.0d0
      Construct(ConstrNew)%W5FileGlazingSysHeight = 0.0d0
    END IF  ! End of check if new window constructions have to be created
  END DO  ! End of loop over unshaded and shaded window constructions
END DO  ! End of loop over storm window objects

RETURN
END SUBROUTINE CreateStormWindowConstructions

SUBROUTINE ModifyWindow(SurfNum,ErrorsFound,AddedSubSurfaces)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Fred Winkelmann
          !       DATE WRITTEN   Feb 2002
          !       MODIFIED       June 2004, FCW: SinAzim, CosAzim, SinTilt, CosTilt, OutNormVec, GrossArea
          !                       and Perimeter weren't being set for created window for case when
          !                       window from Window5DataFile had two different glazing systems. Also,
          !                       GrossArea and Perimeter of original window were not being recalculated.
          !                      October 2007, LKL: Net area for shading calculations was not being
          !                       recalculated.
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! If a window from the Window5DataFile has one glazing system, modify the
          ! vertex coordinates of the original window to correspond to the dimensions
          ! of the glazing system on the Data File.
          ! If a window from the Window5DataFile has two different glazing systems, split
          ! the window into two separate windows with different properties and adjust the
          ! vertices of these windows taking into account the dimensions of the glazing systems
          ! on the Data File and the width and orientation of the mullion that separates
          ! the glazing systems.

          ! METHODOLOGY EMPLOYED:na
          ! REFERENCES:na

          ! USE STATEMENTS:
  USE InputProcessor, ONLY: FindItemInList
  USE General, ONLY: RoundSigDigits
  USE Vectors

  IMPLICIT NONE    ! Enforce explicit typing of all variables in this routine


          ! SUBROUTINE ARGUMENT DEFINITIONS:
  INTEGER, INTENT(IN)       :: SurfNum     ! SurfNum has construction of glazing system from Window5 Data File;
                                           ! If there is a second glazing systme on the Data File, SurfNum+1
                                           ! has the construction of the second glazing system.

  LOGICAL, INTENT(INOUT)    :: ErrorsFound ! Set to true if errors found
  INTEGER, INTENT(INOUT)    :: AddedSubSurfaces ! Subsurfaces added when window references a
                                                ! 2-glazing system Window5 data file entry
          ! SUBROUTINE PARAMETER DEFINITIONS:
          ! na

          ! INTERFACE BLOCK SPECIFICATIONS:
          ! na

          ! DERIVED TYPE DEFINITIONS:
  type rectangularwindow
    type(vector), dimension(4) :: Vertex
  end type rectangularwindow

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
!unused1208  INTEGER :: TotSurfacesPrev                 ! Total number of surfaces before splitting window
!unused1208  INTEGER :: loop                            ! DO loop index
  REAL(r64)    :: H,W                             ! Height and width of original window (m)
!unused1208  REAL(r64)    :: MulWidth                        ! Mullion width (m)
  REAL(r64)    :: h1,w1                           ! height and width of first glazing system (m)
!unused1208  REAL(r64)    :: h2,w2                           ! height and width of second glazing system (m)
  type (vector) TVect
!unused1208  type (rectangularwindow) :: NewCoord
  type (rectangularwindow) :: OriginalCoord
  INTEGER :: IConst                          ! Construction number of first glazing system
  INTEGER :: IConst2                         ! Construction number of second glazing system
  CHARACTER(len=MaxNameLength) :: Const2Name ! Name of construction of second glazing system
!unused1208  REAL(r64)    :: AreaNew                         ! Sum of areas of the two glazing systems (m2)

IConst = SurfaceTmp(SurfNum)%Construction

! Height and width of original window
TVect=SurfaceTmp(SurfNum)%Vertex(3)-SurfaceTmp(SurfNum)%Vertex(2)
W = VecLength(TVect)  !SQRT((X(3)-X(2))**2 + (Y(3)-Y(2))**2 + (Z(3)-Z(2))**2)
TVect=SurfaceTmp(SurfNum)%Vertex(2)-SurfaceTmp(SurfNum)%Vertex(1)
H = VecLength(TVect)  !SQRT((X(1)-X(2))**2 + (Y(1)-Y(2))**2 + (Z(1)-Z(2))**2)

! Save coordinates of original window in case Window 5 data overwrites.
OriginalCoord%Vertex(1:SurfaceTmp(SurfNum)%Sides)=SurfaceTmp(SurfNum)%Vertex(1:SurfaceTmp(SurfNum)%Sides)

! Height and width of first glazing system
h1  = Construct(IConst)%W5FileGlazingSysHeight
w1  = Construct(IConst)%W5FileGlazingSysWidth

Const2Name = TRIM(Construct(IConst)%Name)//':2'
IConst2 = FindItemInList(Const2Name, Construct%Name,TotConstructs)

IF(IConst2 == 0) THEN  ! Only one glazing system on Window5 Data File for this window.

  ! So... original dimensions and area of window are used (entered in IDF)
  ! Warning if dimensions of original window differ from those on Data File by more than 10%

  IF(ABS((H-h1)/H) > 0.10d0 .OR. ABS((W-w1)/W) > 0.10d0) THEN

    IF (DisplayExtraWarnings) THEN
      CALL ShowWarningError('SurfaceGeometry: ModifyWindow: Window '//TRIM(SurfaceTmp(SurfNum)%Name)// &
       ' uses the Window5 Data File Construction '//TRIM(Construct(IConst)%Name))
      CALL ShowContinueError('The height '//TRIM(RoundSigDigits(H,3))//'(m) or width '// &
       TRIM(RoundSigDigits(W,3))//' (m) of this window differs by more than 10%')
      CALL ShowContinueError('from the corresponding height '//TRIM(RoundSigDigits(h1,3))// &
       ' (m) or width '//TRIM(RoundSigDigits(w1,3))//' (m) on the Window5 Data file.')
      CALL ShowContinueError('This will affect the frame heat transfer calculation if the frame in the Data File entry')
      CALL ShowContinueError('is not uniform, i.e., has sections with different geometry and/or thermal properties.')
    ELSE
      Warning1Count=Warning1Count+1
    ENDIF

  END IF

     ! Calculate net area for base surface
  SurfaceTmp(SurfaceTmp(SurfNum)%BaseSurf)%Area =  &
         SurfaceTmp(SurfaceTmp(SurfNum)%BaseSurf)%Area - SurfaceTmp(SurfNum)%Area
  IF (SurfaceTmp(SurfaceTmp(SurfNum)%BaseSurf)%Area <= 0.0d0) THEN
    CALL ShowSevereError('Subsurfaces have too much area for base surface='//  &
                         TRIM(SurfaceTmp(SurfaceTmp(SurfNum)%BaseSurf)%Name))
    CALL ShowContinueError('Subsurface creating error='//TRIM(SurfaceTmp(SurfNum)%Name))
    ErrorsFound=.true.
  ENDIF

     ! Net area of base surface with unity window multipliers (used in shadowing checks)
  SurfaceTmp(SurfaceTmp(SurfNum)%BaseSurf)%NetAreaShadowCalc =  &
     SurfaceTmp(SurfaceTmp(SurfNum)%BaseSurf)%NetAreaShadowCalc -   &
         SurfaceTmp(SurfNum)%Area/SurfaceTmp(SurfNum)%Multiplier

ELSE ! Two glazing systems on Window5 data file for this window

! if exterior window, okay.

  IF (SurfaceTmp(SurfNum)%ExtBoundCond == ExternalEnvironment) THEN
    !There are two glazing systems (separated by a vertical or horizontal mullion) on the Window5 Data File.
    ! Fill in geometry data for the second window (corresponding to the second glazing system on the data file.
    ! The first glazing system is assumed to be at left for vertical mullion, at bottom for horizontal mullion.
    ! The second glazing system is assumed to be at right for vertical mullion, at top for horizontal mullion.
    ! The lower left-hand corner of the original window (its vertex #2) is assumed to coincide with
    ! vertex #2 of the first glazing system.

    IF (DisplayExtraWarnings) THEN
      CALL ShowMessage('SurfaceGeometry: ModifyWindow: Window '// &
                      TRIM(SurfaceTmp(SurfNum)%Name)//' has been replaced with the Window 5/6 two glazing system="'//  &
                      TRIM(Construct(IConst)%Name)//'".')
      CALL ShowContinueError('Note that originally entered dimensions are overridden.')
    ELSE
      Warning2Count=Warning2Count+1
    ENDIF

      ! Allocate another window
    CALL AddWindow(SurfNum,ErrorsFound,AddedSubSurfaces)

  ELSEIF (SurfaceTmp(SurfNum)%ExtBoundCond > 0) THEN ! Interior window, specified  ! not external environment

    IF (DisplayExtraWarnings) THEN
      CALL ShowWarningError('SurfaceGeometry: ModifyWindow: Interior Window '// &
                      TRIM(SurfaceTmp(SurfNum)%Name)//' has been replaced with the Window 5/6 two glazing system="'//  &
                      TRIM(Construct(IConst)%Name)//'".')
      CALL ShowContinueError('Please check to make sure interior window is correct. '//  &
         'Note that originally entered dimensions are overridden.')
    ELSE
      Warning3Count=Warning3Count+1
    ENDIF

    CALL AddWindow(SurfNum,ErrorsFound,AddedSubSurfaces)

  ELSE    ! Interior window, specified not entered

    CALL ShowSevereError('SurfaceGeometry: ModifyWindow: Interior Window '// &
                    TRIM(SurfaceTmp(SurfNum)%Name)//' is a window in an adjacent zone.')
    CALL ShowContinueError('Attempted to add/reverse Window 5/6 multiple glazing system="'//  &
                    TRIM(Construct(IConst)%Name)//'".')
    CALL ShowContinueError('Cannot use these Window 5/6 constructs for these Interior Windows. Program will terminate.')
    ErrorsFound=.true.

  ENDIF

END IF ! End of check if one or two glazing systems are on the Window5 Data File

END SUBROUTINE ModifyWindow

SUBROUTINE AddWindow(SurfNum,ErrorsFound,AddedSubSurfaces)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Linda Lawrie
          !       DATE WRITTEN   Nov 2008
          !       MODIFIED       na
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! This routine is called from ModifyWindow to add a window.  Allows it to be
          ! called in more than one place in the calling routine so as to be able to have
          ! specific warnings or errors issued.

          ! METHODOLOGY EMPLOYED:
          ! na

          ! REFERENCES:
          ! na

          ! USE STATEMENTS:
  USE InputProcessor, ONLY: FindItemInList
  USE General, ONLY: RoundSigDigits
  USE Vectors

  IMPLICIT NONE ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
  INTEGER, INTENT(IN)       :: SurfNum     ! SurfNum has construction of glazing system from Window5 Data File;
                                           ! If there is a second glazing systme on the Data File, SurfNum+1
                                           ! has the construction of the second glazing system.

  LOGICAL, INTENT(INOUT)    :: ErrorsFound ! Set to true if errors found
  INTEGER, INTENT(INOUT)    :: AddedSubSurfaces ! Subsurfaces added when window references a
                                                ! 2-glazing system Window5 data file entry

          ! SUBROUTINE PARAMETER DEFINITIONS:
          ! na

          ! INTERFACE BLOCK SPECIFICATIONS:
          ! na

          ! DERIVED TYPE DEFINITIONS:
  type rectangularwindow
    type(vector), dimension(4) :: Vertex
  end type rectangularwindow


          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
  INTEGER :: TotSurfacesPrev                 ! Total number of surfaces before splitting window
  INTEGER :: loop                            ! DO loop index
  REAL(r64)    :: H,W                             ! Height and width of original window (m)
  REAL(r64)    :: MulWidth                        ! Mullion width (m)
  REAL(r64)    :: h1,w1                           ! height and width of first glazing system (m)
  REAL(r64)    :: h2,w2                           ! height and width of second glazing system (m)
  REAL(r64)    :: xa,ya,za,xb,yb,zb               ! Vertex intermediate variables (m)
  REAL(r64)    :: dx,dy                           ! Vertex displacements from original window (m)
  type (vector) TVect
  type (rectangularwindow) :: NewCoord
  type (rectangularwindow) :: OriginalCoord
  INTEGER :: IConst                          ! Construction number of first glazing system
  INTEGER :: IConst2                         ! Construction number of second glazing system
  CHARACTER(len=MaxNameLength) :: Const2Name ! Name of construction of second glazing system
  REAL(r64)    :: AreaNew                         ! Sum of areas of the two glazing systems (m2)

  IConst = SurfaceTmp(SurfNum)%Construction

  ! Height and width of original window
  TVect=SurfaceTmp(SurfNum)%Vertex(3)-SurfaceTmp(SurfNum)%Vertex(2)
  W = VecLength(TVect)  !SQRT((X(3)-X(2))**2 + (Y(3)-Y(2))**2 + (Z(3)-Z(2))**2)
  TVect=SurfaceTmp(SurfNum)%Vertex(2)-SurfaceTmp(SurfNum)%Vertex(1)
  H = VecLength(TVect)  !SQRT((X(1)-X(2))**2 + (Y(1)-Y(2))**2 + (Z(1)-Z(2))**2)

  ! Save coordinates of original window in case Window 5 data overwrites.
  OriginalCoord%Vertex(1:SurfaceTmp(SurfNum)%Sides)=SurfaceTmp(SurfNum)%Vertex(1:SurfaceTmp(SurfNum)%Sides)

  ! Height and width of first glazing system
  h1  = Construct(IConst)%W5FileGlazingSysHeight
  w1  = Construct(IConst)%W5FileGlazingSysWidth

  Const2Name = TRIM(Construct(IConst)%Name)//':2'
  IConst2 = FindItemInList(Const2Name, Construct%Name,TotConstructs)

    AddedSubSurfaces = AddedSubSurfaces + 1
    TotSurfacesPrev = TotSurfaces
    ALLOCATE(SurfaceTmpSave(TotSurfacesPrev))
    DO loop = 1,TotSurfacesPrev
      SurfaceTmpSave(loop) = SurfaceTmp(loop)
    END DO
    DEALLOCATE(SurfaceTmp)
    TotSurfaces = TotSurfaces + 1
    ALLOCATE(SurfaceTmp(TotSurfaces))
    DO loop = 1,TotSurfacesPrev
      SurfaceTmp(loop) = SurfaceTmpSave(loop)
    END DO
    DEALLOCATE(SurfaceTmpSave)

    ALLOCATE(SurfaceTmp(TotSurfaces)%Vertex(4))

    SurfaceTmp(TotSurfaces)%Name = TRIM(SurfaceTmp(SurfNum)%Name)//':2'
    SurfaceTmp(TotSurfaces)%Construction = IConst2
    SurfaceTmp(TotSurfaces)%ConstructionStoredInputValue = IConst2
    SurfaceTmp(TotSurfaces)%Class = SurfaceTmp(SurfNum)%Class
    SurfaceTmp(TotSurfaces)%Azimuth = SurfaceTmp(SurfNum)%Azimuth
    ! Sine and cosine of azimuth and tilt
    SurfaceTmp(TotSurfaces)%SinAzim = SurfaceTmp(SurfNum)%SinAzim
    SurfaceTmp(TotSurfaces)%CosAzim = SurfaceTmp(SurfNum)%CosAzim
    SurfaceTmp(TotSurfaces)%SinTilt = SurfaceTmp(SurfNum)%SinTilt
    SurfaceTmp(TotSurfaces)%CosTilt = SurfaceTmp(SurfNum)%CosTilt
    ! Outward normal unit vector (pointing away from room)
    SurfaceTmp(TotSurfaces)%Centroid = SurfaceTmp(SurfNum)%Centroid
    SurfaceTmp(TotSurfaces)%lcsx = SurfaceTmp(SurfNum)%lcsx
    SurfaceTmp(TotSurfaces)%lcsy = SurfaceTmp(SurfNum)%lcsy
    SurfaceTmp(TotSurfaces)%lcsz = SurfaceTmp(SurfNum)%lcsz
    SurfaceTmp(TotSurfaces)%NewellAreaVector = SurfaceTmp(SurfNum)%NewellAreaVector
    SurfaceTmp(TotSurfaces)%OutNormVec = SurfaceTmp(SurfNum)%OutNormVec
    SurfaceTmp(TotSurfaces)%Reveal = SurfaceTmp(SurfNum)%Reveal
    SurfaceTmp(TotSurfaces)%Shape = SurfaceTmp(SurfNum)%Shape
    SurfaceTmp(TotSurfaces)%Sides = SurfaceTmp(SurfNum)%Sides
    SurfaceTmp(TotSurfaces)%Tilt = SurfaceTmp(SurfNum)%Tilt
    SurfaceTmp(TotSurfaces)%HeatTransSurf = SurfaceTmp(SurfNum)%HeatTransSurf
    SurfaceTmp(TotSurfaces)%BaseSurfName = SurfaceTmp(SurfNum)%BaseSurfName
    SurfaceTmp(TotSurfaces)%BaseSurf = SurfaceTmp(SurfNum)%BaseSurf
    SurfaceTmp(TotSurfaces)%ZoneName = SurfaceTmp(SurfNum)%ZoneName
    SurfaceTmp(TotSurfaces)%Zone = SurfaceTmp(SurfNum)%Zone
    SurfaceTmp(TotSurfaces)%ExtBoundCondName = SurfaceTmp(SurfNum)%ExtBoundCondName
    SurfaceTmp(TotSurfaces)%ExtBoundCond = SurfaceTmp(SurfNum)%ExtBoundCond
    SurfaceTmp(TotSurfaces)%ExtSolar = SurfaceTmp(SurfNum)%ExtSolar
    SurfaceTmp(TotSurfaces)%ExtWind = SurfaceTmp(SurfNum)%ExtWind
    SurfaceTmp(TotSurfaces)%ViewFactorGround = SurfaceTmp(SurfNum)%ViewFactorGround
    SurfaceTmp(TotSurfaces)%ViewFactorSky = SurfaceTmp(SurfNum)%ViewFactorSky
    SurfaceTmp(TotSurfaces)%ViewFactorGroundIR = SurfaceTmp(SurfNum)%ViewFactorGroundIR
    SurfaceTmp(TotSurfaces)%ViewFactorSkyIR = SurfaceTmp(SurfNum)%ViewFactorSkyIR
    SurfaceTmp(TotSurfaces)%OSCPtr = SurfaceTmp(SurfNum)%OSCPtr
    SurfaceTmp(TotSurfaces)%SchedShadowSurfIndex = SurfaceTmp(SurfNum)%SchedShadowSurfIndex
    SurfaceTmp(TotSurfaces)%ShadowSurfSchedVaries = SurfaceTmp(SurfNum)%ShadowSurfSchedVaries
    SurfaceTmp(TotSurfaces)%MaterialMovInsulExt = SurfaceTmp(SurfNum)%MaterialMovInsulExt
    SurfaceTmp(TotSurfaces)%MaterialMovInsulInt = SurfaceTmp(SurfNum)%MaterialMovInsulInt
    SurfaceTmp(TotSurfaces)%SchedMovInsulExt = SurfaceTmp(SurfNum)%SchedMovInsulExt
    SurfaceTmp(TotSurfaces)%WindowShadingControlPtr = SurfaceTmp(SurfNum)%WindowShadingControlPtr
    SurfaceTmp(TotSurfaces)%ShadedConstruction = SurfaceTmp(SurfNum)%ShadedConstruction
    SurfaceTmp(TotSurfaces)%FrameDivider = SurfaceTmp(SurfNum)%FrameDivider
    SurfaceTmp(TotSurfaces)%Multiplier = SurfaceTmp(SurfNum)%Multiplier
    SurfaceTmp(TotSurfaces)%NetAreaShadowCalc = SurfaceTmp(SurfNum)%NetAreaShadowCalc

    MulWidth = Construct(IConst)%W5FileMullionWidth
    w2  = Construct(IConst2)%W5FileGlazingSysWidth
    h2  = Construct(IConst2)%W5FileGlazingSysHeight

    ! Correction to net area of base surface. Add back in the original glazing area and subtract the
    ! area of the two glazing systems. Note that for Surface(SurfNum)%Class = 'Window' the effect
    ! of a window multiplier is included in the glazing area. Note that frame areas are subtracted later.

    AreaNew = SurfaceTmp(SurfNum)%Multiplier * (h1*w1 + h2*w2)  ! both glazing systems
       ! Adjust net area for base surface
    SurfaceTmp(SurfaceTmp(SurfNum)%BaseSurf)%Area =  &
           SurfaceTmp(SurfaceTmp(SurfNum)%BaseSurf)%Area - AreaNew

       ! Net area of base surface with unity window multipliers (used in shadowing checks)
    SurfaceTmp(SurfaceTmp(SurfNum)%BaseSurf)%NetAreaShadowCalc =  &
    SurfaceTmp(SurfaceTmp(SurfNum)%BaseSurf)%NetAreaShadowCalc - AreaNew/SurfaceTmp(SurfNum)%Multiplier

       ! Reset area, etc. of original window
    SurfaceTmp(SurfNum)%Area = SurfaceTmp(SurfNum)%Multiplier * (h1*w1)
    SurfaceTmp(SurfNum)%GrossArea = SurfaceTmp(SurfNum)%Area
    SurfaceTmp(SurfNum)%NetAreaShadowCalc = h1*w1
    SurfaceTmp(SurfNum)%Perimeter = 2*(h1+w1)
    SurfaceTmp(SurfNum)%Height = h1
    SurfaceTmp(SurfNum)%Width  = w1
       ! Set area, etc. of new window
    SurfaceTmp(TotSurfaces)%Area = SurfaceTmp(TotSurfaces)%Multiplier * (h2*w2)
    SurfaceTmp(TotSurfaces)%GrossArea = SurfaceTmp(TotSurfaces)%Area
    SurfaceTmp(TotSurfaces)%NetAreaShadowCalc = h2*w2
    SurfaceTmp(TotSurfaces)%Perimeter = 2*(h2+w2)
    SurfaceTmp(TotSurfaces)%Height = h2
    SurfaceTmp(TotSurfaces)%Width  = w2

    IF (SurfaceTmp(SurfaceTmp(SurfNum)%BaseSurf)%Area <= 0.0d0) THEN
      CALL ShowSevereError('SurfaceGeometry: ModifyWindow: Subsurfaces have too much area for base surface='//  &
                         TRIM(SurfaceTmp(SurfaceTmp(SurfNum)%BaseSurf)%Name))
      CALL ShowContinueError('Subsurface (window) creating error='//TRIM(SurfaceTmp(SurfNum)%Name))
      CALL ShowContinueError('This window has been replaced by two windows from the Window5 Data File of total area '//  &
                             TRIM(RoundSigDigits(AreaNew,2))//' m2')
      ErrorsFound=.true.
    ENDIF

    ! Assign vertices to the new window; modify vertices of original window.
    ! In the following, vertices are numbered counter-clockwise with vertex #1 at the upper left.

    IF(Construct(IConst)%W5FileMullionOrientation == Vertical) THEN

      ! VERTICAL MULLION: original window is modified to become left-hand glazing (system #1);
      ! new window is created to become right-hand glazing (system #2)

      ! Left-hand glazing

      ! Vertex 1
      dx = 0.0d0
      dy = H - h1
      xa = OriginalCoord%Vertex(1)%x + (dy/H)*(OriginalCoord%Vertex(2)%x-OriginalCoord%Vertex(1)%x)
      ya = OriginalCoord%Vertex(1)%y + (dy/H)*(OriginalCoord%Vertex(2)%y-OriginalCoord%Vertex(1)%y)
      za = OriginalCoord%Vertex(1)%z + (dy/H)*(OriginalCoord%Vertex(2)%z-OriginalCoord%Vertex(1)%z)
      xb = OriginalCoord%Vertex(4)%x + (dy/H)*(OriginalCoord%Vertex(3)%x-OriginalCoord%Vertex(4)%x)
      yb = OriginalCoord%Vertex(4)%y + (dy/H)*(OriginalCoord%Vertex(3)%y-OriginalCoord%Vertex(4)%y)
      zb = OriginalCoord%Vertex(4)%z + (dy/H)*(OriginalCoord%Vertex(3)%z-OriginalCoord%Vertex(4)%z)
      NewCoord%Vertex(1)%x = xa + (dx/W)*(xb-xa)
      NewCoord%Vertex(1)%y = ya + (dx/W)*(yb-ya)
      NewCoord%Vertex(1)%z = za + (dx/W)*(zb-za)

      ! Vertex 2
      dx = 0.0d0
      dy = H
      xa = OriginalCoord%Vertex(1)%x + (dy/H)*(OriginalCoord%Vertex(2)%x-OriginalCoord%Vertex(1)%x)
      ya = OriginalCoord%Vertex(1)%y + (dy/H)*(OriginalCoord%Vertex(2)%y-OriginalCoord%Vertex(1)%y)
      za = OriginalCoord%Vertex(1)%z + (dy/H)*(OriginalCoord%Vertex(2)%z-OriginalCoord%Vertex(1)%z)
      xb = OriginalCoord%Vertex(4)%x + (dy/H)*(OriginalCoord%Vertex(3)%x-OriginalCoord%Vertex(4)%x)
      yb = OriginalCoord%Vertex(4)%y + (dy/H)*(OriginalCoord%Vertex(3)%y-OriginalCoord%Vertex(4)%y)
      zb = OriginalCoord%Vertex(4)%z + (dy/H)*(OriginalCoord%Vertex(3)%z-OriginalCoord%Vertex(4)%z)
      NewCoord%Vertex(2)%x = xa + (dx/W)*(xb-xa)
      NewCoord%Vertex(2)%y = ya + (dx/W)*(yb-ya)
      NewCoord%Vertex(2)%z = za + (dx/W)*(zb-za)

      ! Vertex 3
      dx = w1
      dy = H
      xa = OriginalCoord%Vertex(1)%x + (dy/H)*(OriginalCoord%Vertex(2)%x-OriginalCoord%Vertex(1)%x)
      ya = OriginalCoord%Vertex(1)%y + (dy/H)*(OriginalCoord%Vertex(2)%y-OriginalCoord%Vertex(1)%y)
      za = OriginalCoord%Vertex(1)%z + (dy/H)*(OriginalCoord%Vertex(2)%z-OriginalCoord%Vertex(1)%z)
      xb = OriginalCoord%Vertex(4)%x + (dy/H)*(OriginalCoord%Vertex(3)%x-OriginalCoord%Vertex(4)%x)
      yb = OriginalCoord%Vertex(4)%y + (dy/H)*(OriginalCoord%Vertex(3)%y-OriginalCoord%Vertex(4)%y)
      zb = OriginalCoord%Vertex(4)%z + (dy/H)*(OriginalCoord%Vertex(3)%z-OriginalCoord%Vertex(4)%z)
      NewCoord%Vertex(3)%x = xa + (dx/W)*(xb-xa)
      NewCoord%Vertex(3)%y = ya + (dx/W)*(yb-ya)
      NewCoord%Vertex(3)%z = za + (dx/W)*(zb-za)

      ! Vertex 4
      dx = w1
      dy = H - h1
      xa = OriginalCoord%Vertex(1)%x + (dy/H)*(OriginalCoord%Vertex(2)%x-OriginalCoord%Vertex(1)%x)
      ya = OriginalCoord%Vertex(1)%y + (dy/H)*(OriginalCoord%Vertex(2)%y-OriginalCoord%Vertex(1)%y)
      za = OriginalCoord%Vertex(1)%z + (dy/H)*(OriginalCoord%Vertex(2)%z-OriginalCoord%Vertex(1)%z)
      xb = OriginalCoord%Vertex(4)%x + (dy/H)*(OriginalCoord%Vertex(3)%x-OriginalCoord%Vertex(4)%x)
      yb = OriginalCoord%Vertex(4)%y + (dy/H)*(OriginalCoord%Vertex(3)%y-OriginalCoord%Vertex(4)%y)
      zb = OriginalCoord%Vertex(4)%z + (dy/H)*(OriginalCoord%Vertex(3)%z-OriginalCoord%Vertex(4)%z)
      NewCoord%Vertex(4)%x = xa + (dx/W)*(xb-xa)
      NewCoord%Vertex(4)%y = ya + (dx/W)*(yb-ya)
      NewCoord%Vertex(4)%z = za + (dx/W)*(zb-za)

      DO loop = 1,SurfaceTmp(SurfNum)%Sides
        SurfaceTmp(SurfNum)%Vertex(loop)  = NewCoord%Vertex(loop)
      END DO

      ! Right-hand glazing

      ! Vertex 1
      dx = w1 + MulWidth
      dy = H - (h1+h2)/2.0d0
      xa = OriginalCoord%Vertex(1)%x + (dy/H)*(OriginalCoord%Vertex(2)%x-OriginalCoord%Vertex(1)%x)
      ya = OriginalCoord%Vertex(1)%y + (dy/H)*(OriginalCoord%Vertex(2)%y-OriginalCoord%Vertex(1)%y)
      za = OriginalCoord%Vertex(1)%z + (dy/H)*(OriginalCoord%Vertex(2)%z-OriginalCoord%Vertex(1)%z)
      xb = OriginalCoord%Vertex(4)%x + (dy/H)*(OriginalCoord%Vertex(3)%x-OriginalCoord%Vertex(4)%x)
      yb = OriginalCoord%Vertex(4)%y + (dy/H)*(OriginalCoord%Vertex(3)%y-OriginalCoord%Vertex(4)%y)
      zb = OriginalCoord%Vertex(4)%z + (dy/H)*(OriginalCoord%Vertex(3)%z-OriginalCoord%Vertex(4)%z)
      NewCoord%Vertex(1)%x = xa + (dx/W)*(xb-xa)
      NewCoord%Vertex(1)%y = ya + (dx/W)*(yb-ya)
      NewCoord%Vertex(1)%z = za + (dx/W)*(zb-za)

      ! Vertex 2
      dx = w1 + MulWidth
      dy = H + (h2-h1)/2.0d0
      xa = OriginalCoord%Vertex(1)%x + (dy/H)*(OriginalCoord%Vertex(2)%x-OriginalCoord%Vertex(1)%x)
      ya = OriginalCoord%Vertex(1)%y + (dy/H)*(OriginalCoord%Vertex(2)%y-OriginalCoord%Vertex(1)%y)
      za = OriginalCoord%Vertex(1)%z + (dy/H)*(OriginalCoord%Vertex(2)%z-OriginalCoord%Vertex(1)%z)
      xb = OriginalCoord%Vertex(4)%x + (dy/H)*(OriginalCoord%Vertex(3)%x-OriginalCoord%Vertex(4)%x)
      yb = OriginalCoord%Vertex(4)%y + (dy/H)*(OriginalCoord%Vertex(3)%y-OriginalCoord%Vertex(4)%y)
      zb = OriginalCoord%Vertex(4)%z + (dy/H)*(OriginalCoord%Vertex(3)%z-OriginalCoord%Vertex(4)%z)
      NewCoord%Vertex(2)%x = xa + (dx/W)*(xb-xa)
      NewCoord%Vertex(2)%y = ya + (dx/W)*(yb-ya)
      NewCoord%Vertex(2)%z = za + (dx/W)*(zb-za)

      ! Vertex 3
      dx = w1 + MulWidth + w2
      dy = H + (h2-h1)/2.0d0
      xa = OriginalCoord%Vertex(1)%x + (dy/H)*(OriginalCoord%Vertex(2)%x-OriginalCoord%Vertex(1)%x)
      ya = OriginalCoord%Vertex(1)%y + (dy/H)*(OriginalCoord%Vertex(2)%y-OriginalCoord%Vertex(1)%y)
      za = OriginalCoord%Vertex(1)%z + (dy/H)*(OriginalCoord%Vertex(2)%z-OriginalCoord%Vertex(1)%z)
      xb = OriginalCoord%Vertex(4)%x + (dy/H)*(OriginalCoord%Vertex(3)%x-OriginalCoord%Vertex(4)%x)
      yb = OriginalCoord%Vertex(4)%y + (dy/H)*(OriginalCoord%Vertex(3)%y-OriginalCoord%Vertex(4)%y)
      zb = OriginalCoord%Vertex(4)%z + (dy/H)*(OriginalCoord%Vertex(3)%z-OriginalCoord%Vertex(4)%z)
      NewCoord%Vertex(3)%x = xa + (dx/W)*(xb-xa)
      NewCoord%Vertex(3)%y = ya + (dx/W)*(yb-ya)
      NewCoord%Vertex(3)%z = za + (dx/W)*(zb-za)

      ! Vertex 4
      dx = w1 + MulWidth + w2
      dy = H - (h1+h2)/2.0d0
      xa = OriginalCoord%Vertex(1)%x + (dy/H)*(OriginalCoord%Vertex(2)%x-OriginalCoord%Vertex(1)%x)
      ya = OriginalCoord%Vertex(1)%y + (dy/H)*(OriginalCoord%Vertex(2)%y-OriginalCoord%Vertex(1)%y)
      za = OriginalCoord%Vertex(1)%z + (dy/H)*(OriginalCoord%Vertex(2)%z-OriginalCoord%Vertex(1)%z)
      xb = OriginalCoord%Vertex(4)%x + (dy/H)*(OriginalCoord%Vertex(3)%x-OriginalCoord%Vertex(4)%x)
      yb = OriginalCoord%Vertex(4)%y + (dy/H)*(OriginalCoord%Vertex(3)%y-OriginalCoord%Vertex(4)%y)
      zb = OriginalCoord%Vertex(4)%z + (dy/H)*(OriginalCoord%Vertex(3)%z-OriginalCoord%Vertex(4)%z)
      NewCoord%Vertex(4)%x = xa + (dx/W)*(xb-xa)
      NewCoord%Vertex(4)%y = ya + (dx/W)*(yb-ya)
      NewCoord%Vertex(4)%z = za + (dx/W)*(zb-za)

      DO loop = 1,SurfaceTmp(TotSurfaces)%Sides
        SurfaceTmp(TotSurfaces)%Vertex(loop)  = NewCoord%Vertex(loop)
      END DO

    ELSE ! Horizontal mullion

      ! HORIZONTAL MULLION: original window is modified to become bottom glazing (system #1);
      ! new window is created to become top glazing (system #2)

      ! Bottom glazing

      ! Vertex 1
      dx = 0.0d0
      dy = H - h1
      xa = OriginalCoord%Vertex(1)%x + (dy/H)*(OriginalCoord%Vertex(2)%x-OriginalCoord%Vertex(1)%x)
      ya = OriginalCoord%Vertex(1)%y + (dy/H)*(OriginalCoord%Vertex(2)%y-OriginalCoord%Vertex(1)%y)
      za = OriginalCoord%Vertex(1)%z + (dy/H)*(OriginalCoord%Vertex(2)%z-OriginalCoord%Vertex(1)%z)
      xb = OriginalCoord%Vertex(4)%x + (dy/H)*(OriginalCoord%Vertex(3)%x-OriginalCoord%Vertex(4)%x)
      yb = OriginalCoord%Vertex(4)%y + (dy/H)*(OriginalCoord%Vertex(3)%y-OriginalCoord%Vertex(4)%y)
      zb = OriginalCoord%Vertex(4)%z + (dy/H)*(OriginalCoord%Vertex(3)%z-OriginalCoord%Vertex(4)%z)
      NewCoord%Vertex(1)%x = xa + (dx/W)*(xb-xa)
      NewCoord%Vertex(1)%y = ya + (dx/W)*(yb-ya)
      NewCoord%Vertex(1)%z = za + (dx/W)*(zb-za)

      ! Vertex 2
      dx = 0.0d0
      dy = H
      xa = OriginalCoord%Vertex(1)%x + (dy/H)*(OriginalCoord%Vertex(2)%x-OriginalCoord%Vertex(1)%x)
      ya = OriginalCoord%Vertex(1)%y + (dy/H)*(OriginalCoord%Vertex(2)%y-OriginalCoord%Vertex(1)%y)
      za = OriginalCoord%Vertex(1)%z + (dy/H)*(OriginalCoord%Vertex(2)%z-OriginalCoord%Vertex(1)%z)
      xb = OriginalCoord%Vertex(4)%x + (dy/H)*(OriginalCoord%Vertex(3)%x-OriginalCoord%Vertex(4)%x)
      yb = OriginalCoord%Vertex(4)%y + (dy/H)*(OriginalCoord%Vertex(3)%y-OriginalCoord%Vertex(4)%y)
      zb = OriginalCoord%Vertex(4)%z + (dy/H)*(OriginalCoord%Vertex(3)%z-OriginalCoord%Vertex(4)%z)
      NewCoord%Vertex(2)%x = xa + (dx/W)*(xb-xa)
      NewCoord%Vertex(2)%y = ya + (dx/W)*(yb-ya)
      NewCoord%Vertex(2)%z = za + (dx/W)*(zb-za)

      ! Vertex 3
      dx = w1
      dy = H
      xa = OriginalCoord%Vertex(1)%x + (dy/H)*(OriginalCoord%Vertex(2)%x-OriginalCoord%Vertex(1)%x)
      ya = OriginalCoord%Vertex(1)%y + (dy/H)*(OriginalCoord%Vertex(2)%y-OriginalCoord%Vertex(1)%y)
      za = OriginalCoord%Vertex(1)%z + (dy/H)*(OriginalCoord%Vertex(2)%z-OriginalCoord%Vertex(1)%z)
      xb = OriginalCoord%Vertex(4)%x + (dy/H)*(OriginalCoord%Vertex(3)%x-OriginalCoord%Vertex(4)%x)
      yb = OriginalCoord%Vertex(4)%y + (dy/H)*(OriginalCoord%Vertex(3)%y-OriginalCoord%Vertex(4)%y)
      zb = OriginalCoord%Vertex(4)%z + (dy/H)*(OriginalCoord%Vertex(3)%z-OriginalCoord%Vertex(4)%z)
      NewCoord%Vertex(3)%x = xa + (dx/W)*(xb-xa)
      NewCoord%Vertex(3)%y = ya + (dx/W)*(yb-ya)
      NewCoord%Vertex(3)%z = za + (dx/W)*(zb-za)

      ! Vertex 4
      dx = w1
      dy = H - h1
      xa = OriginalCoord%Vertex(1)%x + (dy/H)*(OriginalCoord%Vertex(2)%x-OriginalCoord%Vertex(1)%x)
      ya = OriginalCoord%Vertex(1)%y + (dy/H)*(OriginalCoord%Vertex(2)%y-OriginalCoord%Vertex(1)%y)
      za = OriginalCoord%Vertex(1)%z + (dy/H)*(OriginalCoord%Vertex(2)%z-OriginalCoord%Vertex(1)%z)
      xb = OriginalCoord%Vertex(4)%x + (dy/H)*(OriginalCoord%Vertex(3)%x-OriginalCoord%Vertex(4)%x)
      yb = OriginalCoord%Vertex(4)%y + (dy/H)*(OriginalCoord%Vertex(3)%y-OriginalCoord%Vertex(4)%y)
      zb = OriginalCoord%Vertex(4)%z + (dy/H)*(OriginalCoord%Vertex(3)%z-OriginalCoord%Vertex(4)%z)
      NewCoord%Vertex(4)%x = xa + (dx/W)*(xb-xa)
      NewCoord%Vertex(4)%y = ya + (dx/W)*(yb-ya)
      NewCoord%Vertex(4)%z = za + (dx/W)*(zb-za)

      DO loop = 1,SurfaceTmp(SurfNum)%Sides
        SurfaceTmp(SurfNum)%Vertex(loop)  = NewCoord%Vertex(loop)
      END DO

      ! Top glazing

      ! Vertex 1
      dx = (w1 - w2)/2.0d0
      dy = H - (h1+h2+MulWidth)
      xa = OriginalCoord%Vertex(1)%x + (dy/H)*(OriginalCoord%Vertex(2)%x-OriginalCoord%Vertex(1)%x)
      ya = OriginalCoord%Vertex(1)%y + (dy/H)*(OriginalCoord%Vertex(2)%y-OriginalCoord%Vertex(1)%y)
      za = OriginalCoord%Vertex(1)%z + (dy/H)*(OriginalCoord%Vertex(2)%z-OriginalCoord%Vertex(1)%z)
      xb = OriginalCoord%Vertex(4)%x + (dy/H)*(OriginalCoord%Vertex(3)%x-OriginalCoord%Vertex(4)%x)
      yb = OriginalCoord%Vertex(4)%y + (dy/H)*(OriginalCoord%Vertex(3)%y-OriginalCoord%Vertex(4)%y)
      zb = OriginalCoord%Vertex(4)%z + (dy/H)*(OriginalCoord%Vertex(3)%z-OriginalCoord%Vertex(4)%z)
      NewCoord%Vertex(1)%x = xa + (dx/W)*(xb-xa)
      NewCoord%Vertex(1)%y = ya + (dx/W)*(yb-ya)
      NewCoord%Vertex(1)%z = za + (dx/W)*(zb-za)

      ! Vertex 2
      dx = (w1 - w2)/2.0d0
      dy = H - (h1+MulWidth)
      xa = OriginalCoord%Vertex(1)%x + (dy/H)*(OriginalCoord%Vertex(2)%x-OriginalCoord%Vertex(1)%x)
      ya = OriginalCoord%Vertex(1)%y + (dy/H)*(OriginalCoord%Vertex(2)%y-OriginalCoord%Vertex(1)%y)
      za = OriginalCoord%Vertex(1)%z + (dy/H)*(OriginalCoord%Vertex(2)%z-OriginalCoord%Vertex(1)%z)
      xb = OriginalCoord%Vertex(4)%x + (dy/H)*(OriginalCoord%Vertex(3)%x-OriginalCoord%Vertex(4)%x)
      yb = OriginalCoord%Vertex(4)%y + (dy/H)*(OriginalCoord%Vertex(3)%y-OriginalCoord%Vertex(4)%y)
      zb = OriginalCoord%Vertex(4)%z + (dy/H)*(OriginalCoord%Vertex(3)%z-OriginalCoord%Vertex(4)%z)
      NewCoord%Vertex(2)%x = xa + (dx/W)*(xb-xa)
      NewCoord%Vertex(2)%y = ya + (dx/W)*(yb-ya)
      NewCoord%Vertex(2)%z = za + (dx/W)*(zb-za)

      ! Vertex 3
      dx = (w1 + w2)/2.0d0
      dy = H - (h1+MulWidth)
      xa = OriginalCoord%Vertex(1)%x + (dy/H)*(OriginalCoord%Vertex(2)%x-OriginalCoord%Vertex(1)%x)
      ya = OriginalCoord%Vertex(1)%y + (dy/H)*(OriginalCoord%Vertex(2)%y-OriginalCoord%Vertex(1)%y)
      za = OriginalCoord%Vertex(1)%z + (dy/H)*(OriginalCoord%Vertex(2)%z-OriginalCoord%Vertex(1)%z)
      xb = OriginalCoord%Vertex(4)%x + (dy/H)*(OriginalCoord%Vertex(3)%x-OriginalCoord%Vertex(4)%x)
      yb = OriginalCoord%Vertex(4)%y + (dy/H)*(OriginalCoord%Vertex(3)%y-OriginalCoord%Vertex(4)%y)
      zb = OriginalCoord%Vertex(4)%z + (dy/H)*(OriginalCoord%Vertex(3)%z-OriginalCoord%Vertex(4)%z)
      NewCoord%Vertex(3)%x = xa + (dx/W)*(xb-xa)
      NewCoord%Vertex(3)%y = ya + (dx/W)*(yb-ya)
      NewCoord%Vertex(3)%z = za + (dx/W)*(zb-za)

      ! Vertex 4
      dx = (w1 + w2)/2.0d0
      dy = H - (h1+h2+MulWidth)
      xa = OriginalCoord%Vertex(1)%x + (dy/H)*(OriginalCoord%Vertex(2)%x-OriginalCoord%Vertex(1)%x)
      ya = OriginalCoord%Vertex(1)%y + (dy/H)*(OriginalCoord%Vertex(2)%y-OriginalCoord%Vertex(1)%y)
      za = OriginalCoord%Vertex(1)%z + (dy/H)*(OriginalCoord%Vertex(2)%z-OriginalCoord%Vertex(1)%z)
      xb = OriginalCoord%Vertex(4)%x + (dy/H)*(OriginalCoord%Vertex(3)%x-OriginalCoord%Vertex(4)%x)
      yb = OriginalCoord%Vertex(4)%y + (dy/H)*(OriginalCoord%Vertex(3)%y-OriginalCoord%Vertex(4)%y)
      zb = OriginalCoord%Vertex(4)%z + (dy/H)*(OriginalCoord%Vertex(3)%z-OriginalCoord%Vertex(4)%z)
      NewCoord%Vertex(4)%x = xa + (dx/W)*(xb-xa)
      NewCoord%Vertex(4)%y = ya + (dx/W)*(yb-ya)
      NewCoord%Vertex(4)%z = za + (dx/W)*(zb-za)

      DO loop = 1,SurfaceTmp(TotSurfaces)%Sides
        SurfaceTmp(TotSurfaces)%Vertex(loop)  = NewCoord%Vertex(loop)
      END DO

    END IF  ! End of check if vertical or horizontal mullion

  RETURN

END SUBROUTINE AddWindow

SUBROUTINE TransformVertsByAspect(SurfNum,NSides)
          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Brent T Griffith
          !       DATE WRITTEN   April 2003
          !       MODIFIED       na
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! Alter input for surface geometry
          ! Optimizing building design for energy can involve
          !  altering building geometry.  Rather than assemble routines to transform
          !  geometry through pre-processing on input, it may be simpler to change
          !  vertices within EnergyPlus since it already reads the data from the input
          !  file and there would no longer be a need to rewrite the text data.
          !  This is essentially a crude hack to allow adjusting geometry with
          !  a single parameter...
          !

          ! METHODOLOGY EMPLOYED:
          ! once vertices have been converted to WCS, change them to reflect a different aspect
          ! ratio for the entire building based on user input.
          ! This routine is called once for each surface by subroutine GetVertices

          ! REFERENCES:
          ! na

          ! USE STATEMENTS:
  USE DataIPShortCuts
  USE InputProcessor

 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


          ! SUBROUTINE PARAMETER DEFINITIONS:
  CHARACTER(len=*), PARAMETER :: CurrentModuleObject='GeometryTransform'

          ! INTERFACE BLOCK SPECIFICATIONS
          ! na

          ! DERIVED TYPE DEFINITIONS
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
  CHARACTER(len=MaxNameLength), DIMENSION(1) :: cAlphas
  REAL(r64), DIMENSION(2) :: rNumerics
  INTEGER            :: NAlphas
  INTEGER            :: NNum
  INTEGER            :: IOSTAT
  REAL(r64),SAVE          :: OldAspectRatio
  REAL(r64),SAVE          :: NewAspectRatio
  Logical, save      :: firstTime = .true.
  Logical, save      :: noTransform = .true.
  CHARACTER(len=2),save   :: transformPlane
  INTEGER            :: N
  REAL(r64)          :: Xo, XnoRot, Xtrans
  REAL(r64)          :: Yo, YnoRot, Ytrans
  !begin execution
  !get user input...
  IF (firstTime) then
    IF (GetNumObjectsFound(CurrentModuleObject) == 1) then
       CALL GetObjectItem(CurrentModuleObject,1,cAlphas,NAlphas,rNumerics,NNum,IOSTAT,  &
                   AlphaBlank=lAlphaFieldBlanks,NumBlank=lNumericFieldBlanks,  &
                   AlphaFieldnames=cAlphaFieldNames,NumericFieldNames=cNumericFieldNames)
       OldAspectRatio = rNumerics(1)
       NewAspectRatio = rNumerics(2)
       transformPlane = cAlphas(1)
       IF (transformPlane /= 'XY') then
         CALL ShowWarningError(CurrentModuleObject//': invalid '//TRIM(cAlphaFieldNames(1))//  &
           '="'//TRIM(cAlphas(1))//'...ignored.')
       ENDIF
       firstTime   = .false.
       noTransform = .false.
       AspectTransform = .true.
       IF (WorldCoordSystem) THEN
         CALL ShowWarningError(CurrentModuleObject//': must use Relative Coordinate System.  '// &
               'Transform request ignored.')
         noTransform=.true.
         AspectTransform=.false.
       ENDIF
    ELSE
       firstTime = .false.
    Endif
  endif
  If (noTransform) return

  !check surface type.
  IF (.not. SurfaceTmp(SurfNum)%HeatTransSurf) THEN
    ! Site Shading do not get transformed.
    IF (SurfaceTmp(SurfNum)%Class == SurfaceClass_Detached_F) return
  ENDIF


    !testing method of transforming  x and y coordinates as follows


    ! this works if not rotated wrt north axis ... but if it is, then trouble
    ! try to first derotate it , transform by aspect and then rotate back.

    DO N=1,NSides
      Xo = SurfaceTmp(SurfNum)%Vertex(N)%X ! world coordinates.... shifted by relative north angle...
      Yo = SurfaceTmp(SurfNum)%Vertex(N)%Y
      ! next derotate the building
      XnoRot=Xo * CosBldgRelNorth + Yo * SinBldgRelNorth
      YnoRot=Yo * CosBldgRelNorth - Xo * SinBldgRelNorth
      ! translate
      Xtrans = XnoRot * SQRT(NewAspectRatio/OldAspectRatio)
      Ytrans = YnoRot * SQRT(OldAspectRatio/NewAspectRatio)
      ! rerotate
      SurfaceTmp(SurfNum)%Vertex(N)%X = Xtrans * CosBldgRelNorth - Ytrans * SinBldgRelNorth

      SurfaceTmp(SurfNum)%Vertex(N)%Y = Xtrans * SinBldgRelNorth + Ytrans * CosBldgRelNorth
    ENDDO

  Return

END SUBROUTINE TransformVertsByAspect

SUBROUTINE CalcSurfaceCentroid

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         B. Griffith
          !       DATE WRITTEN   Feb. 2004
          !       MODIFIED       na
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! compute centroid of all the surfaces in the main
          ! surface structure. Store the vertex coordinates of
          ! the centroid in the 'SURFACE' derived type.

          ! METHODOLOGY EMPLOYED:
          ! The centroid of triangle is easily computed by averaging the vertices
          ! The centroid of a quadrilateral is computed by area weighting the centroids
          ! of two triangles.
          ! (Algorithm would need to be changed for higher order
          ! polygons with more than four sides).

          ! REFERENCES:
          ! na

          ! USE STATEMENTS:
    USE Vectors
    USE General, ONLY: RoundSigDigits

    IMPLICIT NONE    ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
          ! na

          ! SUBROUTINE PARAMETER DEFINITIONS:
          ! na

          ! INTERFACE BLOCK SPECIFICATIONS
          ! na

          ! DERIVED TYPE DEFINITIONS
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    Type(vector), Dimension(3)   :: Triangle1 !working struct for a 3-sided surface
    Type(vector), Dimension(3)   :: Triangle2 !working struct for a 3-sided surface

    INTEGER   :: thisSurf  ! working variable for do loop
    REAL(r64) :: Tri1Area  ! working variable for denominator
    REAL(r64) :: Tri2Area  ! working variable for denominator
    REAL(r64) :: TotalArea ! working variable for denominator
    REAL(r64) :: Xcm       ! temporary X coord for centriod
    REAL(r64) :: Ycm       ! temporary Y coord for centriod
    REAL(r64) :: Zcm       ! temporary Z coord for centriod
    REAL(r64) :: XcmTri1   ! temporary X coord for centriod of triangle 1
    REAL(r64) :: YcmTri1   ! temporary Y coord for centriod of triangle 1
    REAL(r64) :: ZcmTri1   ! temporary Z coord for centriod of triangle 1
    REAL(r64) :: XcmTri2   ! temporary X coord for centriod of triangle 2
    REAL(r64) :: YcmTri2   ! temporary Y coord for centriod of triangle 2
    REAL(r64) :: ZcmTri2   ! temporary Z coord for centriod of triangle 2
    type(vector) :: VecAvg ! Average (calc for multisided polygons (>4 sides))
    integer   :: vert
    integer   :: negZcount  ! for warning error in surface centroids

    negZcount=0

    ! loop through all the surfaces
    Do thisSurf=1, TotSurfaces

!      IF (Surface(thisSurf)%CLASS == 'INTMASS') CYCLE
      IF (Surface(thisSurf)%CLASS == SurfaceClass_IntMass) CYCLE

      !re-init
      Xcm = 0.0d0
      Ycm = 0.0d0
      Zcm = 0.0d0


      SELECT CASE (surface(thissurf)%sides)  !is this a 3- or 4-sided surface

      CASE (3) !3-sided polygon
        ! centriod is simple average
        Xcm = sum(surface(thisSurf)%vertex%x) / 3.0d0
        Ycm = sum(surface(thisSurf)%vertex%y) / 3.0d0
        Zcm = sum(surface(thisSurf)%vertex%z) / 3.0d0

      CASE (4) !4-sided polygon

        ! re-init
        Triangle1%X = 0.0d0
        Triangle1%Y = 0.0d0
        Triangle1%Z = 0.0d0

        Triangle2%X = 0.0d0
        Triangle2%Y = 0.0d0
        Triangle2%Z = 0.0d0

        XcmTri1     = 0.0d0
        YcmTri1     = 0.0d0
        ZcmTri1     = 0.0d0

        XcmTri2     = 0.0d0
        YcmTri2     = 0.0d0
        ZcmTri2     = 0.0d0

        Tri1Area    = 0.0d0
        Tri2Area    = 0.0d0

        ! split into 2 3-sided polygons (Triangle 1 and Triangle 2)
        Triangle1%X = surface(thisSurf)%vertex( (/1,2,3/) )%X
        Triangle1%Y = surface(thisSurf)%vertex( (/1,2,3/) )%Y
        Triangle1%Z = surface(thisSurf)%vertex( (/1,2,3/) )%Z

        Triangle2%X = surface(thisSurf)%vertex( (/1,3,4/) )%X
        Triangle2%Y = surface(thisSurf)%vertex( (/1,3,4/) )%Y
        Triangle2%Z = surface(thisSurf)%vertex( (/1,3,4/) )%Z

        ! get area of triangles.
        Tri1Area = AreaPolygon(3,Triangle1)
        Tri2Area = AreaPolygon(3,Triangle2)

        ! get total Area of quad.
        TotalArea = surface(thisSurf)%grossarea

        IF (TotalArea <= 0.0d0 ) then
           !catch a problem....
            CALL ShowWarningError('CalcSurfaceCentroid: zero area surface, for surface='//TRIM(surface(thisSurf)%Name))
            cycle
        endif
        ! get centroid of Triangle 1
        XcmTri1 = sum(Triangle1%x) / 3.0d0
        YcmTri1 = sum(Triangle1%y) / 3.0d0
        ZcmTri1 = sum(Triangle1%z) / 3.0d0

        ! get centroid of Triangle 2
        XcmTri2 = sum(Triangle2%x) / 3.0d0
        YcmTri2 = sum(Triangle2%y) / 3.0d0
        ZcmTri2 = sum(Triangle2%z) / 3.0d0

        ! find area weighted combination of the two centroids.

        Xcm = (XcmTri1*Tri1Area + XcmTri2*Tri2Area) / TotalArea
        Ycm = (YcmTri1*Tri1Area + YcmTri2*Tri2Area) / TotalArea
        Zcm = (ZcmTri1*Tri1Area + ZcmTri2*Tri2Area) / TotalArea

      CASE (5:) !multi-sided polygon
         ! (Maybe triangulate?  For now, use old "z" average method")
         ! and X and Y -- straight average

!        X1=MINVAL(Surface(thisSurf)%Vertex(1:Surface(thisSurf)%Sides)%X)
!        X2=MAXVAL(Surface(thisSurf)%Vertex(1:Surface(thisSurf)%Sides)%X)
!        Y1=MINVAL(Surface(thisSurf)%Vertex(1:Surface(thisSurf)%Sides)%Y)
!        Y2=MAXVAL(Surface(thisSurf)%Vertex(1:Surface(thisSurf)%Sides)%Y)
!        Z1=MINVAL(Surface(thisSurf)%Vertex(1:Surface(thisSurf)%Sides)%Z)
!        Z2=MAXVAL(Surface(thisSurf)%Vertex(1:Surface(thisSurf)%Sides)%Z)
!        Xcm=(X1+X2)/2.0d0
!        Ycm=(Y1+Y2)/2.0d0
!        Zcm=(Z1+Z2)/2.0d0

        ! Calc centroid as average of surfaces
        VecAvg=vector(0.0d0,0.0d0,0.0d0)

        do vert=1,Surface(thisSurf)%Sides
          VecAvg=VecAvg + Surface(thisSurf)%Vertex(vert)
        enddo
        VecAvg=VecAvg/REAL(Surface(thisSurf)%Sides,r64)
        Xcm=VecAvg%x
        Ycm=VecAvg%y
        Zcm=VecAvg%z

      CASE DEFAULT

      IF (Surface(thisSurf)%Name /= Blank) THEN
          CALL ShowWarningError('CalcSurfaceCentroid: caught problem with # of sides, for surface='//TRIM(surface(thisSurf)%Name))
          CALL ShowContinueError('... number of sides must be >= 3, this surface # sides='//  &
                           TRIM(RoundSigDigits(surface(thisSurf)%Sides)))
      ELSE
          CALL ShowWarningError('CalcSurfaceCentroid: caught problem with # of sides, for surface=#'//  &
             TRIM(RoundSigDigits(thisSurf)))
          CALL ShowContinueError('...surface name is blank. Examine surfaces -- '//  &
             'this may be a problem with ill-formed interzone surfaces.')
          CALL ShowContinueError('... number of sides must be >= 3, this surface # sides='//  &
                           TRIM(RoundSigDigits(surface(thisSurf)%Sides)))
      ENDIF

      END SELECT

      ! store result in the surface structure in DataSurfaces
      Surface(thissurf)%centroid%x = Xcm
      Surface(thissurf)%centroid%y = Ycm
      Surface(thissurf)%centroid%z = Zcm

      if (Zcm < 0.0d0) then
        if (Surface(thisSurf)%ExtWind .or. Surface(thisSurf)%ExtBoundCond == ExternalEnvironment) negZcount=negZcount+1
      endif

    ENDDO  !loop through surfaces

    if (negZcount > 0) then
      CALL ShowWarningError('CalcSurfaceCentroid: '//TRIM(RoundSigDigits(negZcount))//  &
              ' Surfaces have the Z coordinate < 0.')
      CALL ShowContinueError('...in any calculations, Wind Speed will be 0.0 for these surfaces.')
      CALL ShowContinueError('...in any calculations, Outside temperatures will be the '//   &
         'outside temperature + '//TRIM(RoundSigDigits(WeatherFileTempModCoeff,3))//' for these surfaces.')
      CALL ShowContinueError('...that is, these surfaces will have conditions as though at ground level.')
    endif

    RETURN

END SUBROUTINE CalcSurfaceCentroid

SUBROUTINE SetupShadeSurfacesForSolarCalcs
          ! SUBROUTINE INFORMATION:
          !       AUTHOR         B. Griffith
          !       DATE WRITTEN   Dec. 2008
          !       MODIFIED       na
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE:
          ! determine if Shading surfaces need full solar calcs because they
          ! are also used to define geometry of an active solar component.
          ! Normally, a shading surface is not included in calculations of incident solar, only shading
          !

          ! METHODOLOGY EMPLOYED:
          ! Mine solar renewables input and collect surface names.
          ! find shading surfaces with names that match those in solar objects.
          ! setup flags for shading surfaces so that the solar renewables can resuse incident solar calcs
          ! new solar component models that use shading surfaces will have to extend the code here.

          ! REFERENCES:
          ! na

          ! USE STATEMENTS:
  USE InputProcessor, ONLY: GetNumObjectsFound, GetObjectItem, FindItemInList, SameString
  USE DataIPShortCuts
  USE DataHeatBalance, ONLY:

  IMPLICIT NONE    ! Enforce explicit typing of all variables in this routine

          ! SUBROUTINE ARGUMENT DEFINITIONS:
          ! na

          ! SUBROUTINE PARAMETER DEFINITIONS:
          ! na

          ! INTERFACE BLOCK SPECIFICATIONS
          ! na

          ! DERIVED TYPE DEFINITIONS
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
  CHARACTER(len=MaxNameLength),  ALLOCATABLE, DIMENSION(:) :: TmpCandidateSurfaceNames
  CHARACTER(len=MaxNameLength),  ALLOCATABLE, DIMENSION(:) :: TmpCandidateICSSurfaceNames
  CHARACTER(len=MaxNameLength),  ALLOCATABLE, DIMENSION(:) :: TmpCandidateICSBCTypeNames
  INTEGER :: NumCandidateNames
  INTEGER :: NumOfCollectors
  INTEGER :: NumOfICSUnits
  INTEGER :: NumOfFlatPlateUnits
  INTEGER :: NumPVTs
  INTEGER :: NumPVs
  INTEGER :: SurfNum
  INTEGER :: found
  INTEGER :: CollectorNum
  INTEGER :: PVTNum
  INTEGER :: PVNum
  INTEGER :: NumAlphas ! Number of alpha names being passed
  INTEGER :: NumNumbers   ! Number of numeric parameters being passed
  INTEGER :: IOStatus

  !First collect names of surfaces referenced by active solar components
  cCurrentModuleObject = 'SolarCollector:FlatPlate:Water'
  NumOfFlatPlateUnits = GetNumObjectsFound(cCurrentModuleObject)
  cCurrentModuleObject = 'SolarCollector:FlatPlate:PhotovoltaicThermal'
  NumPVTs              = GetNumObjectsFound(cCurrentModuleObject)
  cCurrentModuleObject = 'Generator:Photovoltaic'
  NumPVs                 = GetNumObjectsFound(cCurrentModuleObject )
  cCurrentModuleObject = 'SolarCollector:IntegralCollectorStorage'
  NumOfICSUnits = GetNumObjectsFound(cCurrentModuleObject)

  NumCandidateNames = NumOfFlatPlateUnits + NumPVTs + NumPVs + NumOfICSUnits
  NumOfCollectors = NumOfFlatPlateUnits + NumOfICSUnits

  ALLOCATE(TmpCandidateSurfaceNames(NumCandidateNames), TmpCandidateICSSurfaceNames(NumOfCollectors), &
           TmpCandidateICSBCTypeNames(NumOfCollectors))

  IF (NumOfCollectors > 0) THEN
    cCurrentModuleObject = 'SolarCollector:FlatPlate:Water'
    DO CollectorNum = 1, NumOfFlatPlateUnits

      CALL GetObjectItem(cCurrentModuleObject,CollectorNum,cAlphaArgs,NumAlphas,rNumericArgs,NumNumbers,IOStatus)

      TmpCandidateSurfaceNames(CollectorNum) = cAlphaArgs(3)
      TmpCandidateICSBCTypeNames(CollectorNum) = ' '
    ENDDO
  ENDIF

  IF (NumPVTs > 0) THEN
    cCurrentModuleObject = 'SolarCollector:FlatPlate:PhotovoltaicThermal'
    DO PVTNum = 1, NumPVTs

      CALL GetObjectItem(cCurrentModuleObject,PVTNum,cAlphaArgs,NumAlphas,rNumericArgs,NumNumbers,IOStatus)

      TmpCandidateSurfaceNames(NumOfFlatPlateUnits + PVTNum) = cAlphaArgs(2)
    ENDDO
  ENDIF

  IF (NumPVs > 0) THEN
    cCurrentModuleObject = 'Generator:Photovoltaic'
    DO PVNum = 1, NumPVs
      CALL GetObjectItem(cCurrentModuleObject,PVNum,cAlphaArgs,NumAlphas,rNumericArgs,NumNumbers,IOStatus)
      TmpCandidateSurfaceNames(NumOfFlatPlateUnits + NumPVTs + PVNum) = cAlphaArgs(2)
    ENDDO
  ENDIF

  IF (NumOfICSUnits > 0) THEN
    cCurrentModuleObject = 'SolarCollector:IntegralCollectorStorage'
    DO CollectorNum = 1, NumOfICSUnits
      CALL GetObjectItem(cCurrentModuleObject,CollectorNum,cAlphaArgs,NumAlphas,rNumericArgs,NumNumbers,IOStatus)
      TmpCandidateSurfaceNames(NumOfFlatPlateUnits + NumPVTs + NumPVs + CollectorNum) = cAlphaArgs(3)
      TmpCandidateICSSurfaceNames(NumOfFlatPlateUnits + CollectorNum) = cAlphaArgs(3)
      TmpCandidateICSBCTypeNames(NumOfFlatPlateUnits + CollectorNum) = cAlphaArgs(4)
    ENDDO
  ENDIF

  ! loop through all the surfaces
  Do SurfNum=1, TotSurfaces

    Found = FindItemInList(Surface(SurfNum)%name, TmpCandidateSurfaceNames, NumCandidateNames)
    IF (Found > 0) Then
      IF (.NOT. Surface(SurfNum)%HeatTransSurf ) Then ! not BIPV, must be a shading surf with solar device
        ! Setup missing values to allow shading surfaces to model incident solar and wind
        Surface(SurfNum)%ExtSolar = .TRUE.
        Surface(SurfNum)%ExtWind = .TRUE.
        Surface(SurfNum)%ViewFactorGround = 0.5d0 * (1.0d0 - Surface(SurfNum)%CosTilt)

      ENDIF
      ! check if this surface is used for ICS collector mounting and has OthersideCondictionsModel as its
      ! boundary condition
      IF (NumOfICSUnits > 0) Then
        DO CollectorNum = 1, NumOfCollectors
          IF ( SameString(Surface(SurfNum)%name, TmpCandidateICSSurfaceNames(CollectorNum)) .AND. &
               SameString(TmpCandidateICSBCTypeNames(CollectorNum), 'OTHERSIDECONDITIONSMODEL') ) THEN
               Surface(SurfNum)%IsICS = .TRUE.
               Surface(SurfNum)%ICSPtr = CollectorNum
          ENDIF

        END DO
      ENDIF

    ENDIF   ! end of IF (Found > 0) Then

  ENDDO

  DEALLOCATE(TmpCandidateSurfaceNames,TmpCandidateICSBCTypeNames,TmpCandidateICSSurfaceNames)
  RETURN

END SUBROUTINE SetupShadeSurfacesForSolarCalcs

SUBROUTINE CheckConvexity(SurfNum,NSides)

          ! SUBROUTINE INFORMATION:
          !       AUTHOR         Tyler Hoyt
          !       DATE WRITTEN   December 2010
          !       MODIFIED       CR8752 - incorrect note of non-convex polygons
          !       RE-ENGINEERED  na

          ! PURPOSE OF THIS SUBROUTINE: This subroutine verifies the convexity of a
          ! surface that is exposed to the sun in the case that full shading calculations
          ! are required. The calculation conveniently detects collinear points as well,
          ! and returns a list of indices that are collinear within the plane of the surface.

          ! METHODOLOGY EMPLOYED: First the surface is determined to have dimension 2 in
          ! either the xy, yz, or xz plane. That plane is selected to do the testing.
          ! Vectors representing the edges of the polygon and the perpendicular dot product
          ! between adjacent edges are computed. This allows the turning angle to be determined.
          ! If the turning angle is greater than pi/2, it turns to the right, and if it is
          ! less than pi/2, it turns left. The direction of the turn is stored, and if it
          ! changes as the edges are iterated the surface is not convex. Meanwhile it stores
          ! the indices of vertices that are collinear and are later removed.

          ! REFERENCES:
          ! http://mathworld.wolfram.com/ConvexPolygon.html

          ! USE STATEMENTS:
  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

          ! SUBROUTINE PARAMETER DEFINITIONS:
  REAL(r64),PARAMETER :: TurnThreshold = 0.000001d0 ! Sensitivity of convexity test, in radians
  CHARACTER(len=*), PARAMETER :: ErrFmt="(' (',F8.3,',',F8.3,',',F8.3,')')"

          ! INTERFACE BLOCK SPECIFICATIONS
          ! na

          ! DERIVED TYPE DEFINITIONS
          ! na

          ! SUBROUTINE LOCAL VARIABLE DECLARATIONS:
  INTEGER   :: N             ! Loop index
  INTEGER   :: Np1             ! Loop index
  INTEGER   :: Np2             ! Loop index
  REAL(r64) :: Det           ! Determinant for picking projection plane
  REAL(r64) :: DotProd       ! Dot product for determining angle
  REAL(r64) :: Theta         ! Angle between edge vectors
  REAL(r64) :: LastTheta     ! Angle between edge vectors
  REAL(r64) :: V1len         ! Edge vector length
  REAL(r64) :: V2len         ! Edge vector length
  LOGICAL   :: SignFlag      ! Direction of edge turn : .true. is right, .false. is left
  LOGICAL   :: PrevSignFlag  ! Container for the sign of the previous iteration's edge turn
  LOGICAL   :: FirstTimeFlag ! Flag indicating first iteration
  REAL(r64), ALLOCATABLE, SAVE, DIMENSION(:) :: X ! containers for x,y,z vertices of the surface
  REAL(r64), ALLOCATABLE, SAVE, DIMENSION(:) :: Y
  REAL(r64), ALLOCATABLE, SAVE, DIMENSION(:) :: Z
  REAL(r64), ALLOCATABLE, SAVE, DIMENSION(:) :: A    ! containers for convexity test
  REAL(r64), ALLOCATABLE, SAVE, DIMENSION(:) :: B
  INTEGER, ALLOCATABLE, SAVE, DIMENSION(:) :: SurfCollinearVerts ! Array containing indices of collinear vertices
  INTEGER, SAVE :: VertSize  ! size of X,Y,Z,A,B arrays
  REAL(r64) :: cosarg
  INTEGER   :: M             ! Array index for SurfCollinearVerts container
  INTEGER   :: J             ! Loop index
  INTEGER   :: K             ! Loop index
  INTEGER   :: Ind           ! Location of surface vertex to be removed
  LOGICAL, SAVE :: firstTime=.true.
  REAL(r64), SAVE :: ACosZero  ! set on firstTime
  LOGICAL :: SurfCollinearWarning
  CHARACTER(len=132) :: ErrLineOut=Blank ! Character string for producing error messages

  if (firstTime) then
    ACosZero=ACOS(0.0d0)
    ALLOCATE(X(MaxVerticesPerSurface+2))
    ALLOCATE(Y(MaxVerticesPerSurface+2))
    ALLOCATE(Z(MaxVerticesPerSurface+2))
    ALLOCATE(A(MaxVerticesPerSurface+2))
    ALLOCATE(B(MaxVerticesPerSurface+2))
    ALLOCATE(SurfCollinearVerts(MaxVerticesPerSurface))
    VertSize=MaxVerticesPerSurface
    firstTime=.false.
  endif

  if (NSides > VertSize) then
    DEALLOCATE(X)
    DEALLOCATE(Y)
    DEALLOCATE(Z)
    DEALLOCATE(A)
    DEALLOCATE(B)
    DEALLOCATE(SurfCollinearVerts)
    ALLOCATE(X(MaxVerticesPerSurface+2))
    ALLOCATE(Y(MaxVerticesPerSurface+2))
    ALLOCATE(Z(MaxVerticesPerSurface+2))
    ALLOCATE(A(MaxVerticesPerSurface+2))
    ALLOCATE(B(MaxVerticesPerSurface+2))
    ALLOCATE(SurfCollinearVerts(MaxVerticesPerSurface))
    VertSize=MaxVerticesPerSurface
  endif

  DO N = 1, NSides
    X(N) = SurfaceTmp(SurfNum)%Vertex(N)%X
    Y(N) = SurfaceTmp(SurfNum)%Vertex(N)%Y
    Z(N) = SurfaceTmp(SurfNum)%Vertex(N)%Z
  END DO
  X(Nsides+1) = SurfaceTmp(SurfNum)%Vertex(1)%X
  Y(Nsides+1) = SurfaceTmp(SurfNum)%Vertex(1)%Y
  Z(Nsides+1) = SurfaceTmp(SurfNum)%Vertex(1)%Z
  X(Nsides+2) = SurfaceTmp(SurfNum)%Vertex(2)%X
  Y(Nsides+2) = SurfaceTmp(SurfNum)%Vertex(2)%Y
  Z(Nsides+2) = SurfaceTmp(SurfNum)%Vertex(2)%Z


  ! Determine a suitable plane in which to do the tests
  Det = 0.0d0
  DO N = 1, NSides
    Det = Det + X(N)*Y(N+1) - X(N+1)*Y(N)
  END DO
  IF (ABS(Det) > 1.d-4) THEN
    A = X
    B = Y
  ELSE
    Det = 0.0d0
    DO N = 1, NSides
      Det = Det + X(N)*Z(N+1) - X(N+1)*Z(N)
    END DO
    IF (ABS(Det) > 1.d-4) THEN
      A = X
      B = Z
    ELSE
      Det = 0.0d0
      DO N = 1, NSides
        Det = Det + Y(N)*Z(N+1) - Y(N+1)*Z(N)
      END DO
      IF (ABS(Det) > 1.d-4) THEN
        A = Y
        B = Z
      ELSE
        ! This condition should not be reached if the surfaces are guaranteed to be planar already
        CALL ShowSevereError('CheckConvexity: Surface="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
          '" is non-planar.')
        CALL ShowContinueError('Coincident Vertices will be removed as possible.')
        DO N=1,SurfaceTmp(SurfNum)%Sides
          WRITE(ErrLineOut,ErrFmt) SurfaceTmp(SurfNum)%Vertex(N)
          CALL ShowContinueError(ErrLineOut)
        ENDDO
      END IF
    END IF
  END IF

  M = 0
  FirstTimeFlag = .true.
  SurfCollinearWarning=.false.
  DO N = 1, NSides   ! perform convexity test in the plane determined above.
    DotProd = (A(N+1)-A(N))*(B(N+2)-B(N+1))-(B(N+1)-B(N))*(A(N+2)-A(N+1))
    V1len = SQRT((A(N+1)-A(N))**2+(B(N+1)-B(N))**2)
    V2len = SQRT((A(N+2)-A(N+1))**2+(B(N+2)-B(N+1))**2)
    IF (V1Len <= 1.d-8 .or. V2Len <= 1.d-8) CYCLE
    cosarg=DotProd/(V1len * V2len)
    if (cosarg < -1.0d0) then
      cosarg=-1.0d0
    elseif (cosarg > 1.0d0) then
      cosarg=1.0d0
    endif
    Theta   = ACOS(cosarg)
    IF (Theta < (ACosZero-TurnThreshold)) THEN
      SignFlag = .true.
    ELSE
      IF (Theta > (ACosZero+TurnThreshold)) THEN
        SignFlag = .false.
      ELSE   ! Store the index of the collinear vertex for removal
        IF (.not. SurfCollinearWarning) THEN
          IF (DisplayExtraWarnings) THEN
            CALL ShowWarningError('CheckConvexity: Surface="'//TRIM(SurfaceTmp(SurfNum)%Name)//  &
               '", Collinear points have been removed.')
          ENDIF
          SurfCollinearWarning=.true.
        ENDIF
        TotalCoincidentVertices=TotalCoincidentVertices+1
        M = M + 1
        SurfCollinearVerts(M) = N + 1
        CYCLE
      END IF
    END IF

    IF (FirstTimeFlag) THEN
      PrevSignFlag = SignFlag
      FirstTimeFlag = .false.
      CYCLE
    END IF

    IF (SignFlag .neqv. PrevSignFlag) THEN
      IF (SolarDistribution /= MinimalShadowing .and. SurfaceTmp(SurfNum)%ExtSolar) THEN
        IF (DisplayExtraWarnings) THEN
          CALL ShowWarningError('CheckConvexity: Zone="'//trim(Zone(SurfaceTmp(SurfNum)%Zone)%Name)//  &
             '", Surface="'//TRIM(SurfaceTmp(SurfNum)%Name)//'" is non-convex.')
          Np1=N+1
          IF (Np1 > NSides) Np1=Np1-NSides
          Np2=N+2
          IF (Np2 > NSides) Np2=Np2-NSides
          CALL ShowContinueError('...vertex '//trim(RoundSigDigits(N))//' to vertex '//trim(RoundSigDigits(Np1))//  &
             ' to vertex '//trim(RoundSigDigits(Np2)))
          CALL ShowContinueError('...vertex '//trim(RoundSigDigits(N))//'=['//  &
             trim(RoundSigDigits(X(N),2))//','//  &
             trim(RoundSigDigits(Y(N),2))//','//  &
             trim(RoundSigDigits(Z(N),2))//']')
          CALL ShowContinueError('...vertex '//trim(RoundSigDigits(Np1))//'=['//  &
             trim(RoundSigDigits(X(N+1),2))//','//  &
             trim(RoundSigDigits(Y(N+1),2))//','//  &
             trim(RoundSigDigits(Z(N+1),2))//']')
          CALL ShowContinueError('...vertex '//trim(RoundSigDigits(Np2))//'=['//  &
             trim(RoundSigDigits(X(N+2),2))//','//  &
             trim(RoundSigDigits(Y(N+2),2))//','//  &
             trim(RoundSigDigits(Z(N+2),2))//']')
!          CALL ShowContinueError('...theta angle=['//trim(RoundSigDigits(Theta,6))//']')
!          CALL ShowContinueError('...last theta angle=['//trim(RoundSigDigits(LastTheta,6))//']')
        ENDIF
        SurfaceTmp(SurfNum)%IsConvex=.false.
        EXIT
      END IF
    END IF
    PrevSignFlag = SignFlag
    LastTheta=Theta
  END DO

  ! must check to make sure don't remove NSides below 3
  IF (M > 0) THEN ! Remove the collinear points determined above
    IF (NSides-M > 2) THEN
      SurfaceTmp(SurfNum)%Sides = NSides - M
    ELSE  ! too many
      IF (DisplayExtraWarnings) THEN
        CALL ShowWarningError('CheckConvexity: Surface="'//TRIM(SurfaceTmp(SurfNum)%Name)//'" has ['//  &
             trim(RoundSigDigits(M))//'] collinear points.')
        CALL ShowContinueError('...too many to remove all.  Will leave the surface with 3 sides. '//  &
           'But this is now a degenerate surface')
      ENDIF
      TotalDegenerateSurfaces=TotalDegenerateSurfaces+1
      SurfaceTmp(SurfNum)%Sides = MAX(NSides-M,3)
      M=NSides-SurfaceTmp(SurfNum)%Sides
    ENDIF
    DO J = 1, M
      Ind = SurfCollinearVerts(J)
      DO K = Ind, NSides - J
        SurfaceTmp(SurfNum)%Vertex(K-J+1)%X = SurfaceTmp(SurfNum)%Vertex(K-J+2)%X
        SurfaceTmp(SurfNum)%Vertex(K-J+1)%Y = SurfaceTmp(SurfNum)%Vertex(K-J+2)%Y
        SurfaceTmp(SurfNum)%Vertex(K-J+1)%Z = SurfaceTmp(SurfNum)%Vertex(K-J+2)%Z
      END DO
    END DO
  END IF


END SUBROUTINE CheckConvexity

!     NOTICE
!
!     Copyright © 1996-2013 The Board of Trustees of the University of Illinois
!     and The Regents of the University of California through Ernest Orlando Lawrence
!     Berkeley National Laboratory.  All rights reserved.
!
!     Portions of the EnergyPlus software package have been developed and copyrighted
!     by other individuals, companies and institutions.  These portions have been
!     incorporated into the EnergyPlus software package under license.   For a complete
!     list of contributors, see "Notice" located in EnergyPlus.f90.
!
!     NOTICE: The U.S. Government is granted for itself and others acting on its
!     behalf a paid-up, nonexclusive, irrevocable, worldwide license in this data to
!     reproduce, prepare derivative works, and perform publicly and display publicly.
!     Beginning five (5) years after permission to assert copyright is granted,
!     subject to two possible five year renewals, the U.S. Government is granted for
!     itself and others acting on its behalf a paid-up, non-exclusive, irrevocable
!     worldwide license in this data to reproduce, prepare derivative works,
!     distribute copies to the public, perform publicly and display publicly, and to
!     permit others to do so.
!
!     TRADEMARKS: EnergyPlus is a trademark of the US Department of Energy.
!

END MODULE SurfaceGeometry

AirflowNetworkBalanceManager.f90 AirflowNetworkSolver.f90 BaseboardRadiator.f90 BaseboardRadiatorElectric.f90 BaseboardRadiatorSteam.f90 BaseboardRadiatorWater.f90 BranchInputManager.f90 BranchNodeConnections.f90 ConductionTransferFunctionCalc.f90 CoolTower.f90 CostEstimateManager.f90 CurveManager.f90 CVFOnlyRoutines.f90 DataAirflowNetwork.f90 DataAirLoop.f90 DataAirSystems.f90 DataBranchAirLoopPlant.f90 DataBranchNodeConnections.f90 DataBSDFWindow.f90 DataComplexFenestration.f90 DataContaminantBalance.f90 DataConvergParams.f90 DataConversions.f90 DataCostEstimate.f90 DataDaylighting.f90 DataDaylightingDevices.f90 Datadefineequip.f90 DataDElight.f90 DataEnvironment.f90 DataEquivalentLayerWindow.f90 DataErrorTracking.f90 DataGenerators.f90 DataGlobalConstants.f90 DataGlobals.f90 DataHeatBalance.f90 DataHeatBalFanSys.f90 DataHeatBalSurface.f90 DataHVACControllers.f90 DataHVACGlobals.f90 DataInterfaces.f90 DataIPShortCuts.f90 DataLoopNode.f90 DataMoistureBalance.f90 DataMoistureBalanceEMPD.f90 DataOutputs.f90 DataPhotovoltaics.f90 DataPlant.f90 DataPlantPipingSystems.f90 DataPrecisionGlobals.f90 DataReportingFlags.f90 DataRoomAir.f90 DataRootFinder.f90 DataRuntimeLanguage.f90 DataShadowingCombinations.f90 DataSizing.f90 DataStringGlobals.f90 DataSurfaceColors.f90 DataSurfaceLists.f90 DataSurfaces.f90 DataSystemVariables.f90 DataTimings.f90 DataUCSDSharedData.f90 DataVectorTypes.f90 DataViewFactorInformation.f90 DataWater.f90 DataZoneControls.f90 DataZoneEnergyDemands.f90 DataZoneEquipment.f90 DaylightingDevices.f90 DaylightingManager.f90 DElightManagerF.f90 DElightManagerF_NO.f90 DemandManager.f90 DesiccantDehumidifiers.f90 DirectAir.f90 DisplayRoutines.f90 DXCoil.f90 EarthTube.f90 EconomicLifeCycleCost.f90 EconomicTariff.f90 EcoRoof.f90 ElectricPowerGenerators.f90 ElectricPowerManager.f90 EMSManager.f90 EnergyPlus.f90 ExteriorEnergyUseManager.f90 ExternalInterface_NO.f90 FanCoilUnits.f90 FaultsManager.f90 FluidProperties.f90 General.f90 GeneralRoutines.f90 GlobalNames.f90 HeatBalanceAirManager.f90 HeatBalanceConvectionCoeffs.f90 HeatBalanceHAMTManager.f90 HeatBalanceInternalHeatGains.f90 HeatBalanceIntRadExchange.f90 HeatBalanceManager.f90 HeatBalanceMovableInsulation.f90 HeatBalanceSurfaceManager.f90 HeatBalFiniteDifferenceManager.f90 HeatRecovery.f90 Humidifiers.f90 HVACControllers.f90 HVACCooledBeam.f90 HVACDualDuctSystem.f90 HVACDuct.f90 HVACDXSystem.f90 HVACEvapComponent.f90 HVACFanComponent.f90 HVACFurnace.f90 HVACHeatingCoils.f90 HVACHXAssistedCoolingCoil.f90 HVACInterfaceManager.f90 HVACManager.f90 HVACMixerComponent.f90 HVACMultiSpeedHeatPump.f90 HVACSingleDuctInduc.f90 HVACSingleDuctSystem.f90 HVACSplitterComponent.f90 HVACStandAloneERV.f90 HVACSteamCoilComponent.f90 HVACTranspiredCollector.f90 HVACUnitaryBypassVAV.f90 HVACUnitarySystem.f90 HVACVariableRefrigerantFlow.f90 HVACWaterCoilComponent.f90 HVACWatertoAir.f90 HVACWatertoAirMultiSpeedHP.f90 InputProcessor.f90 MatrixDataManager.f90 MixedAir.f90 MoistureBalanceEMPDManager.f90 NodeInputManager.f90 NonZoneEquipmentManager.f90 OutAirNodeManager.f90 OutdoorAirUnit.f90 OutputProcessor.f90 OutputReportPredefined.f90 OutputReports.f90 OutputReportTabular.f90 PackagedTerminalHeatPump.f90 PackagedThermalStorageCoil.f90 Photovoltaics.f90 PhotovoltaicThermalCollectors.f90 PlantAbsorptionChillers.f90 PlantBoilers.f90 PlantBoilersSteam.f90 PlantCentralGSHP.f90 PlantChillers.f90 PlantCondLoopOperation.f90 PlantCondLoopTowers.f90 PlantEIRChillers.f90 PlantEvapFluidCoolers.f90 PlantExhaustAbsorptionChiller.f90 PlantFluidCoolers.f90 PlantGasAbsorptionChiller.f90 PlantGroundHeatExchangers.f90 PlantHeatExchanger.f90 PlantIceThermalStorage.f90 PlantLoadProfile.f90 PlantLoopEquipment.f90 PlantLoopSolver.f90 PlantManager.f90 PlantOutsideEnergySources.f90 PlantPipeHeatTransfer.f90 PlantPipes.f90 PlantPipingSystemManager.f90 PlantPondGroundHeatExchanger.f90 PlantPressureSystem.f90 PlantPumps.f90 PlantSolarCollectors.f90 PlantSurfaceGroundHeatExchanger.f90 PlantUtilities.f90 PlantValves.f90 PlantWaterSources.f90 PlantWaterThermalTank.f90 PlantWatertoWaterGSHP.f90 PlantWaterUse.f90 PollutionAnalysisModule.f90 PoweredInductionUnits.f90 PsychRoutines.f90 Purchasedairmanager.f90 RadiantSystemHighTemp.f90 RadiantSystemLowTemp.f90 RefrigeratedCase.f90 ReportSizingManager.f90 ReturnAirPath.f90 RoomAirManager.f90 RoomAirModelCrossVent.f90 RoomAirModelDisplacementVent.f90 RoomAirModelMundt.f90 RoomAirModelUFAD.f90 RoomAirModelUserTempPattern.f90 RootFinder.f90 RuntimeLanguageProcessor.f90 ScheduleManager.f90 SetPointManager.f90 SimAirServingZones.f90 SimulationManager.f90 SizingManager.f90 SolarReflectionManager.f90 SolarShading.f90 SortAndStringUtilities.f90 sqlite3.c SQLiteCRoutines.c SQLiteFortranRoutines.f90 SQLiteFortranRoutines_NO.f90 StandardRatings.f90 SurfaceGeometry.f90 SystemAvailabilityManager.f90 SystemReports.f90 TarcogComplexFenestration.f90 ThermalChimney.f90 ThermalComfort.f90 UnitHeater.f90 UnitVentilator.f90 UserDefinedComponents.f90 UtilityRoutines.f90 VectorUtilities.f90 VentilatedSlab.f90 WaterManager.f90 WeatherManager.f90 WindowAC.f90 WindowComplexManager.f90 WindowEquivalentLayer.f90 WindowManager.f90 WindTurbine.f90 Zoneairloopequipmentmanager.f90 ZoneContaminantPredictorCorrector.f90 ZoneDehumidifier.f90 Zoneequipmentmanager.f90 ZonePlenumComponent.f90 ZoneTempPredictorCorrector.f90