Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2023, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 : #include <algorithm>
50 : #include <cassert>
51 : #include <cmath>
52 : #include <string>
53 :
54 : // ObjexxFCL Headers
55 : #include <ObjexxFCL/Fmath.hh>
56 : #include <ObjexxFCL/member.functions.hh>
57 : #include <ObjexxFCL/string.functions.hh>
58 :
59 : // EnergyPlus Headers
60 : #include <EnergyPlus/Construction.hh>
61 : #include <EnergyPlus/ConvectionCoefficients.hh>
62 : #include <EnergyPlus/ConvectionConstants.hh>
63 : #include <EnergyPlus/Data/EnergyPlusData.hh>
64 : #include <EnergyPlus/DataEnvironment.hh>
65 : #include <EnergyPlus/DataErrorTracking.hh>
66 : #include <EnergyPlus/DataHeatBalSurface.hh>
67 : #include <EnergyPlus/DataHeatBalance.hh>
68 : #include <EnergyPlus/DataIPShortCuts.hh>
69 : #include <EnergyPlus/DataLoopNode.hh>
70 : #include <EnergyPlus/DataReportingFlags.hh>
71 : #include <EnergyPlus/DataViewFactorInformation.hh>
72 : #include <EnergyPlus/DataWindowEquivalentLayer.hh>
73 : #include <EnergyPlus/DataZoneEquipment.hh>
74 : #include <EnergyPlus/DaylightingManager.hh>
75 : #include <EnergyPlus/DisplayRoutines.hh>
76 : #include <EnergyPlus/EMSManager.hh>
77 : #include <EnergyPlus/General.hh>
78 : #include <EnergyPlus/GlobalNames.hh>
79 : #include <EnergyPlus/HeatBalanceManager.hh>
80 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
81 : #include <EnergyPlus/Material.hh>
82 : #include <EnergyPlus/NodeInputManager.hh>
83 : #include <EnergyPlus/OutAirNodeManager.hh>
84 : #include <EnergyPlus/OutputProcessor.hh>
85 : #include <EnergyPlus/OutputReportPredefined.hh>
86 : #include <EnergyPlus/ScheduleManager.hh>
87 : #include <EnergyPlus/SolarShading.hh>
88 : #include <EnergyPlus/SurfaceGeometry.hh>
89 : #include <EnergyPlus/UtilityRoutines.hh>
90 : #include <EnergyPlus/Vectors.hh>
91 : #include <EnergyPlus/WeatherManager.hh>
92 : #include <EnergyPlus/WindowManager.hh>
93 :
94 : namespace EnergyPlus {
95 :
96 : namespace SurfaceGeometry {
97 :
98 : // Module containing the routines dealing with the Surface Geometry
99 :
100 : // MODULE INFORMATION:
101 : // AUTHOR Linda Lawrie
102 : // DATE WRITTEN June 2000
103 : // MODIFIED DJS (PSU Dec 2006) to add ecoroof
104 : // RE-ENGINEERED na
105 :
106 : // PURPOSE OF THIS MODULE:
107 : // This module performs the functions required of the surface geometry.
108 :
109 : using namespace DataEnvironment;
110 : using namespace DataHeatBalance;
111 : using namespace DataSurfaces;
112 : using DataWindowEquivalentLayer::CFSMAXNL;
113 :
114 771 : static std::string const BlankString;
115 :
116 : int constexpr UnenteredAdjacentZoneSurface = -998; // allows users to enter one zone surface ("Zone")
117 : // referencing another in adjacent zone
118 : int constexpr UnreconciledZoneSurface = -999; // interim value between entering surfaces ("Surface") and reconciling
119 :
120 771 : void AllocateSurfaceWindows(EnergyPlusData &state, int NumSurfaces)
121 : {
122 771 : state.dataSurface->SurfWinA.dimension(state.dataSurface->TotSurfaces, CFSMAXNL + 1, 0.0);
123 771 : state.dataSurface->SurfWinADiffFront.dimension(state.dataSurface->TotSurfaces, CFSMAXNL + 1, 0.0);
124 771 : state.dataSurface->SurfWinACFOverlap.dimension(state.dataSurface->TotSurfaces, state.dataHeatBal->MaxSolidWinLayers, 0.0);
125 :
126 771 : state.dataSurface->SurfWinFrameQRadOutAbs.dimension(NumSurfaces, 0);
127 771 : state.dataSurface->SurfWinFrameQRadInAbs.dimension(NumSurfaces, 0);
128 771 : state.dataSurface->SurfWinDividerQRadOutAbs.dimension(NumSurfaces, 0);
129 771 : state.dataSurface->SurfWinDividerQRadInAbs.dimension(NumSurfaces, 0);
130 771 : state.dataSurface->SurfWinExtBeamAbsByShade.dimension(NumSurfaces, 0);
131 771 : state.dataSurface->SurfWinExtDiffAbsByShade.dimension(NumSurfaces, 0);
132 771 : state.dataSurface->SurfWinIntBeamAbsByShade.dimension(NumSurfaces, 0);
133 771 : state.dataSurface->SurfWinIntSWAbsByShade.dimension(NumSurfaces, 0);
134 771 : state.dataSurface->SurfWinInitialDifSolAbsByShade.dimension(NumSurfaces, 0);
135 771 : state.dataSurface->SurfWinIntLWAbsByShade.dimension(NumSurfaces, 0);
136 771 : state.dataSurface->SurfWinConvHeatFlowNatural.dimension(NumSurfaces, 0);
137 771 : state.dataSurface->SurfWinConvHeatGainToZoneAir.dimension(NumSurfaces, 0);
138 771 : state.dataSurface->SurfWinRetHeatGainToZoneAir.dimension(NumSurfaces, 0);
139 771 : state.dataSurface->SurfWinDividerHeatGain.dimension(NumSurfaces, 0);
140 771 : state.dataSurface->SurfWinBlTsolBmBm.dimension(NumSurfaces, 0);
141 771 : state.dataSurface->SurfWinBlTsolBmDif.dimension(NumSurfaces, 0);
142 771 : state.dataSurface->SurfWinBlTsolDifDif.dimension(NumSurfaces, 0);
143 771 : state.dataSurface->SurfWinBlGlSysTsolBmBm.dimension(NumSurfaces, 0);
144 771 : state.dataSurface->SurfWinBlGlSysTsolDifDif.dimension(NumSurfaces, 0);
145 771 : state.dataSurface->SurfWinScTsolBmBm.dimension(NumSurfaces, 0);
146 771 : state.dataSurface->SurfWinScTsolBmDif.dimension(NumSurfaces, 0);
147 771 : state.dataSurface->SurfWinScTsolDifDif.dimension(NumSurfaces, 0);
148 771 : state.dataSurface->SurfWinScGlSysTsolBmBm.dimension(NumSurfaces, 0);
149 771 : state.dataSurface->SurfWinScGlSysTsolDifDif.dimension(NumSurfaces, 0);
150 771 : state.dataSurface->SurfWinGlTsolBmBm.dimension(NumSurfaces, 0);
151 771 : state.dataSurface->SurfWinGlTsolBmDif.dimension(NumSurfaces, 0);
152 771 : state.dataSurface->SurfWinGlTsolDifDif.dimension(NumSurfaces, 0);
153 771 : state.dataSurface->SurfWinBmSolTransThruIntWinRep.dimension(NumSurfaces, 0);
154 771 : state.dataSurface->SurfWinBmSolAbsdOutsReveal.dimension(NumSurfaces, 0);
155 771 : state.dataSurface->SurfWinBmSolRefldOutsRevealReport.dimension(NumSurfaces, 0);
156 771 : state.dataSurface->SurfWinBmSolAbsdInsReveal.dimension(NumSurfaces, 0);
157 771 : state.dataSurface->SurfWinBmSolRefldInsReveal.dimension(NumSurfaces, 0);
158 771 : state.dataSurface->SurfWinBmSolRefldInsRevealReport.dimension(NumSurfaces, 0);
159 771 : state.dataSurface->SurfWinOutsRevealDiffOntoGlazing.dimension(NumSurfaces, 0);
160 771 : state.dataSurface->SurfWinInsRevealDiffOntoGlazing.dimension(NumSurfaces, 0);
161 771 : state.dataSurface->SurfWinInsRevealDiffIntoZone.dimension(NumSurfaces, 0);
162 771 : state.dataSurface->SurfWinOutsRevealDiffOntoFrame.dimension(NumSurfaces, 0);
163 771 : state.dataSurface->SurfWinInsRevealDiffOntoFrame.dimension(NumSurfaces, 0);
164 771 : state.dataSurface->SurfWinInsRevealDiffOntoGlazingReport.dimension(NumSurfaces, 0);
165 771 : state.dataSurface->SurfWinInsRevealDiffIntoZoneReport.dimension(NumSurfaces, 0);
166 771 : state.dataSurface->SurfWinInsRevealDiffOntoFrameReport.dimension(NumSurfaces, 0);
167 771 : state.dataSurface->SurfWinBmSolAbsdInsRevealReport.dimension(NumSurfaces, 0);
168 771 : state.dataSurface->SurfWinBmSolTransThruIntWinRepEnergy.dimension(NumSurfaces, 0);
169 771 : state.dataSurface->SurfWinBmSolRefldOutsRevealRepEnergy.dimension(NumSurfaces, 0);
170 771 : state.dataSurface->SurfWinBmSolRefldInsRevealRepEnergy.dimension(NumSurfaces, 0);
171 771 : state.dataSurface->SurfWinProfileAngHor.dimension(NumSurfaces, 0);
172 771 : state.dataSurface->SurfWinProfileAngVert.dimension(NumSurfaces, 0);
173 :
174 771 : state.dataSurface->SurfWinShadingFlag.dimension(NumSurfaces, WinShadingType::ShadeOff);
175 771 : state.dataSurface->SurfWinShadingFlagEMSOn.dimension(NumSurfaces, 0);
176 771 : state.dataSurface->SurfWinShadingFlagEMSValue.dimension(NumSurfaces, 0.0);
177 771 : state.dataSurface->SurfWinStormWinFlag.dimension(NumSurfaces, 0);
178 771 : state.dataSurface->SurfWinStormWinFlagPrevDay.dimension(NumSurfaces, 0);
179 771 : state.dataSurface->SurfWinFracTimeShadingDeviceOn.dimension(NumSurfaces, 0);
180 771 : state.dataSurface->SurfWinExtIntShadePrevTS.dimension(NumSurfaces, WinShadingType::ShadeOff);
181 771 : state.dataSurface->SurfWinHasShadeOrBlindLayer.dimension(NumSurfaces, 0);
182 771 : state.dataSurface->SurfWinSurfDayLightInit.dimension(NumSurfaces, 0);
183 771 : state.dataSurface->SurfWinDaylFacPoint.dimension(NumSurfaces, 0);
184 771 : state.dataSurface->SurfWinVisTransSelected.dimension(NumSurfaces, 0);
185 771 : state.dataSurface->SurfWinSwitchingFactor.dimension(NumSurfaces, 0);
186 771 : state.dataSurface->SurfWinTheta.dimension(NumSurfaces, 0);
187 771 : state.dataSurface->SurfWinPhi.dimension(NumSurfaces, 0);
188 771 : state.dataSurface->SurfWinRhoCeilingWall.dimension(NumSurfaces, 0);
189 771 : state.dataSurface->SurfWinRhoFloorWall.dimension(NumSurfaces, 0);
190 771 : state.dataSurface->SurfWinFractionUpgoing.dimension(NumSurfaces, 0);
191 771 : state.dataSurface->SurfWinVisTransRatio.dimension(NumSurfaces, 0);
192 771 : state.dataSurface->SurfWinIRfromParentZone.dimension(NumSurfaces, 0);
193 771 : state.dataSurface->SurfWinFrameArea.dimension(NumSurfaces, 0);
194 771 : state.dataSurface->SurfWinFrameConductance.dimension(NumSurfaces, 0);
195 771 : state.dataSurface->SurfWinFrameSolAbsorp.dimension(NumSurfaces, 0);
196 771 : state.dataSurface->SurfWinFrameVisAbsorp.dimension(NumSurfaces, 0);
197 771 : state.dataSurface->SurfWinFrameEmis.dimension(NumSurfaces, 0);
198 771 : state.dataSurface->SurfWinFrEdgeToCenterGlCondRatio.dimension(NumSurfaces, 1.0);
199 771 : state.dataSurface->SurfWinFrameEdgeArea.dimension(NumSurfaces, 0);
200 771 : state.dataSurface->SurfWinFrameTempIn.dimension(NumSurfaces, 23.0);
201 771 : state.dataSurface->SurfWinFrameTempInOld.dimension(NumSurfaces, 23.0);
202 771 : state.dataSurface->SurfWinFrameTempSurfOut.dimension(NumSurfaces, 23.0);
203 771 : state.dataSurface->SurfWinProjCorrFrOut.dimension(NumSurfaces, 0);
204 771 : state.dataSurface->SurfWinProjCorrFrIn.dimension(NumSurfaces, 0);
205 771 : state.dataSurface->SurfWinDividerType.dimension(NumSurfaces, DataSurfaces::FrameDividerType::DividedLite);
206 771 : state.dataSurface->SurfWinDividerArea.dimension(NumSurfaces, 0);
207 771 : state.dataSurface->SurfWinDividerConductance.dimension(NumSurfaces, 0);
208 771 : state.dataSurface->SurfWinDividerSolAbsorp.dimension(NumSurfaces, 0);
209 771 : state.dataSurface->SurfWinDividerVisAbsorp.dimension(NumSurfaces, 0);
210 771 : state.dataSurface->SurfWinDividerEmis.dimension(NumSurfaces, 0);
211 771 : state.dataSurface->SurfWinDivEdgeToCenterGlCondRatio.dimension(NumSurfaces, 1);
212 771 : state.dataSurface->SurfWinDividerEdgeArea.dimension(NumSurfaces, 0);
213 771 : state.dataSurface->SurfWinDividerTempIn.dimension(NumSurfaces, 23.0);
214 771 : state.dataSurface->SurfWinDividerTempInOld.dimension(NumSurfaces, 23.0);
215 771 : state.dataSurface->SurfWinDividerTempSurfOut.dimension(NumSurfaces, 23.0);
216 771 : state.dataSurface->SurfWinProjCorrDivOut.dimension(NumSurfaces, 0);
217 771 : state.dataSurface->SurfWinProjCorrDivIn.dimension(NumSurfaces, 0);
218 771 : state.dataSurface->SurfWinGlazedFrac.dimension(NumSurfaces, 1);
219 771 : state.dataSurface->SurfWinCenterGlArea.dimension(NumSurfaces, 0);
220 771 : state.dataSurface->SurfWinEdgeGlCorrFac.dimension(NumSurfaces, 1);
221 771 : state.dataSurface->SurfWinOriginalClass.dimension(NumSurfaces, SurfaceClass::None);
222 771 : state.dataSurface->SurfWinShadeAbsFacFace1.dimension(NumSurfaces, 0.5);
223 771 : state.dataSurface->SurfWinShadeAbsFacFace2.dimension(NumSurfaces, 0.5);
224 771 : state.dataSurface->SurfWinConvCoeffWithShade.dimension(NumSurfaces, 0);
225 771 : state.dataSurface->SurfWinOtherConvHeatGain.dimension(NumSurfaces, 0);
226 771 : state.dataSurface->SurfWinBlindNumber.dimension(NumSurfaces, 0);
227 771 : state.dataSurface->SurfWinEffInsSurfTemp.dimension(NumSurfaces, 23.0);
228 771 : state.dataSurface->SurfWinMovableSlats.dimension(NumSurfaces, 0);
229 771 : state.dataSurface->SurfWinSlatAngThisTS.dimension(NumSurfaces, 0);
230 771 : state.dataSurface->SurfWinSlatAngThisTSDeg.dimension(NumSurfaces, 0);
231 771 : state.dataSurface->SurfWinSlatAngThisTSDegEMSon.dimension(NumSurfaces, 0);
232 771 : state.dataSurface->SurfWinSlatAngThisTSDegEMSValue.dimension(NumSurfaces, 0);
233 771 : state.dataSurface->SurfWinSlatsBlockBeam.dimension(NumSurfaces, 0);
234 771 : state.dataSurface->SurfWinSlatsAngIndex.dimension(NumSurfaces, 0);
235 771 : state.dataSurface->SurfWinSlatsAngInterpFac.dimension(NumSurfaces, 0);
236 771 : state.dataSurface->SurfWinProfileAng.dimension(NumSurfaces, 0);
237 771 : state.dataSurface->SurfWinProfAngIndex.dimension(NumSurfaces, 0);
238 771 : state.dataSurface->SurfWinProfAngInterpFac.dimension(NumSurfaces, 0);
239 771 : state.dataSurface->SurfWinBlindBmBmTrans.dimension(NumSurfaces, 0);
240 771 : state.dataSurface->SurfWinBlindAirFlowPermeability.dimension(NumSurfaces, 0);
241 771 : state.dataSurface->SurfWinTotGlazingThickness.dimension(NumSurfaces, 0);
242 771 : state.dataSurface->SurfWinTanProfileAngHor.dimension(NumSurfaces, 0);
243 771 : state.dataSurface->SurfWinTanProfileAngVert.dimension(NumSurfaces, 0);
244 771 : state.dataSurface->SurfWinInsideSillDepth.dimension(NumSurfaces, 0);
245 771 : state.dataSurface->SurfWinInsideReveal.dimension(NumSurfaces, 0);
246 771 : state.dataSurface->SurfWinInsideSillSolAbs.dimension(NumSurfaces, 0);
247 771 : state.dataSurface->SurfWinInsideRevealSolAbs.dimension(NumSurfaces, 0);
248 771 : state.dataSurface->SurfWinOutsideRevealSolAbs.dimension(NumSurfaces, 0);
249 771 : state.dataSurface->SurfWinScreenNumber.dimension(NumSurfaces, 0);
250 771 : state.dataSurface->SurfWinAirflowSource.dimension(NumSurfaces, DataSurfaces::WindowAirFlowSource::Invalid);
251 771 : state.dataSurface->SurfWinAirflowDestination.dimension(NumSurfaces, DataSurfaces::WindowAirFlowDestination::Invalid);
252 771 : state.dataSurface->SurfWinAirflowReturnNodePtr.dimension(NumSurfaces, 0);
253 771 : state.dataSurface->SurfWinMaxAirflow.dimension(NumSurfaces, 0);
254 771 : state.dataSurface->SurfWinAirflowControlType.dimension(NumSurfaces, DataSurfaces::WindowAirFlowControlType::Invalid);
255 771 : state.dataSurface->SurfWinAirflowHasSchedule.dimension(NumSurfaces, 0);
256 771 : state.dataSurface->SurfWinAirflowSchedulePtr.dimension(NumSurfaces, 0);
257 771 : state.dataSurface->SurfWinAirflowThisTS.dimension(NumSurfaces, 0);
258 771 : state.dataSurface->SurfWinTAirflowGapOutlet.dimension(NumSurfaces, 0);
259 771 : state.dataSurface->SurfWinWindowCalcIterationsRep.dimension(NumSurfaces, 0);
260 771 : state.dataSurface->SurfWinVentingOpenFactorMultRep.dimension(NumSurfaces, 0);
261 771 : state.dataSurface->SurfWinInsideTempForVentingRep.dimension(NumSurfaces, 0);
262 771 : state.dataSurface->SurfWinVentingAvailabilityRep.dimension(NumSurfaces, 0);
263 771 : state.dataSurface->SurfWinSkyGndSolarInc.dimension(NumSurfaces, 0);
264 771 : state.dataSurface->SurfWinBmGndSolarInc.dimension(NumSurfaces, 0);
265 771 : state.dataSurface->SurfWinLightWellEff.dimension(NumSurfaces, 1);
266 771 : state.dataSurface->SurfWinSolarDiffusing.dimension(NumSurfaces, 0);
267 771 : state.dataSurface->SurfWinFrameHeatGain.dimension(NumSurfaces, 0);
268 771 : state.dataSurface->SurfWinFrameHeatLoss.dimension(NumSurfaces, 0);
269 771 : state.dataSurface->SurfWinDividerHeatLoss.dimension(NumSurfaces, 0);
270 771 : state.dataSurface->SurfWinTCLayerTemp.dimension(NumSurfaces, 0);
271 771 : state.dataSurface->SurfWinSpecTemp.dimension(NumSurfaces, 0);
272 771 : state.dataSurface->SurfWinWindowModelType.dimension(NumSurfaces, WindowModel::Detailed);
273 771 : state.dataSurface->SurfWinTDDPipeNum.dimension(NumSurfaces, 0);
274 771 : state.dataSurface->SurfWinStormWinConstr.dimension(NumSurfaces, 0);
275 771 : state.dataSurface->SurfActiveConstruction.dimension(NumSurfaces, 0);
276 771 : state.dataSurface->SurfWinActiveShadedConstruction.dimension(NumSurfaces, 0);
277 771 : }
278 :
279 771 : void SetupZoneGeometry(EnergyPlusData &state, bool &ErrorsFound)
280 : {
281 :
282 : // SUBROUTINE INFORMATION:
283 : // AUTHOR George Walton
284 : // DATE WRITTEN September 1977
285 : // MODIFIED April 2002 (FCW): add warning for Solar Distribution
286 : // = FullInteriorExterior when window has reveal
287 : // Add fatal error when triangular window has reveal
288 : // May 2002(FCW): Allow triangular windows to have reveal (subr SHDRVL
289 : // in SolarShading). Remove above warning and fatal error.
290 : // RE-ENGINEERED November 1997 (RKS,LKL)
291 :
292 : // PURPOSE OF THIS SUBROUTINE:
293 : // This subroutine controls the processing of detached shadowing and
294 : // zone surfaces for computing their vertices.
295 :
296 : using namespace DataVectorTypes;
297 : using namespace OutputReportPredefined;
298 :
299 : static constexpr std::string_view RoutineName("SetUpZoneGeometry: ");
300 :
301 : Real64 AverageHeight; // Used to keep track of average height of a surface/zone
302 : Real64 ZMax; // Maximum Z of a surface (detailed outside coefficient calculation)
303 : Real64 ZMin; // Minimum Z of a surface (detailed outside coefficient calculation)
304 : Real64 ZCeilAvg;
305 : Real64 CeilCount;
306 : Real64 ZFlrAvg;
307 : Real64 FloorCount;
308 : Real64 TotSurfArea;
309 : Real64 Z1;
310 : Real64 Z2;
311 1542 : std::string String1;
312 1542 : std::string String2;
313 1542 : std::string String3;
314 : int Count; // To count wall surfaces for ceiling height calculation
315 1542 : Array1D_bool ZoneCeilingHeightEntered;
316 1542 : Array1D<Real64> ZoneCeilingArea;
317 771 : auto &ErrCount = state.dataSurfaceGeometry->ErrCount;
318 : Real64 NominalUwithConvCoeffs;
319 1542 : std::string cNominalU;
320 1542 : std::string cNominalUwithConvCoeffs;
321 : bool isWithConvCoefValid;
322 : bool nonInternalMassSurfacesPresent;
323 : bool DetailedWWR;
324 :
325 : // Zones must have been "gotten" before this call
326 : // The RelNorth variables are used if "relative" coordinates are input as well
327 : // as setting up DaylightingCoords
328 :
329 : // these include building north axis and Building Rotation for Appendix G
330 771 : state.dataSurfaceGeometry->CosBldgRelNorth =
331 771 : std::cos(-(state.dataHeatBal->BuildingAzimuth + state.dataHeatBal->BuildingRotationAppendixG) * DataGlobalConstants::DegToRadians);
332 771 : state.dataSurfaceGeometry->SinBldgRelNorth =
333 771 : std::sin(-(state.dataHeatBal->BuildingAzimuth + state.dataHeatBal->BuildingRotationAppendixG) * DataGlobalConstants::DegToRadians);
334 :
335 : // these are only for Building Rotation for Appendix G when using world coordinate system
336 771 : state.dataSurfaceGeometry->CosBldgRotAppGonly = std::cos(-state.dataHeatBal->BuildingRotationAppendixG * DataGlobalConstants::DegToRadians);
337 771 : state.dataSurfaceGeometry->SinBldgRotAppGonly = std::sin(-state.dataHeatBal->BuildingRotationAppendixG * DataGlobalConstants::DegToRadians);
338 :
339 771 : state.dataSurfaceGeometry->CosZoneRelNorth.allocate(state.dataGlobal->NumOfZones);
340 771 : state.dataSurfaceGeometry->SinZoneRelNorth.allocate(state.dataGlobal->NumOfZones);
341 :
342 771 : ZoneCeilingHeightEntered.dimension(state.dataGlobal->NumOfZones, false);
343 771 : ZoneCeilingArea.dimension(state.dataGlobal->NumOfZones, 0.0);
344 :
345 5585 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
346 :
347 4814 : state.dataSurfaceGeometry->CosZoneRelNorth(ZoneNum) =
348 4814 : std::cos(-state.dataHeatBal->Zone(ZoneNum).RelNorth * DataGlobalConstants::DegToRadians);
349 4814 : state.dataSurfaceGeometry->SinZoneRelNorth(ZoneNum) =
350 4814 : std::sin(-state.dataHeatBal->Zone(ZoneNum).RelNorth * DataGlobalConstants::DegToRadians);
351 : }
352 771 : GetSurfaceData(state, ErrorsFound);
353 :
354 771 : if (ErrorsFound) {
355 0 : state.dataSurfaceGeometry->CosZoneRelNorth.deallocate();
356 0 : state.dataSurfaceGeometry->SinZoneRelNorth.deallocate();
357 0 : return;
358 : }
359 :
360 771 : GetWindowGapAirflowControlData(state, ErrorsFound);
361 :
362 771 : GetStormWindowData(state, ErrorsFound);
363 :
364 771 : if (!ErrorsFound && state.dataSurface->TotStormWin > 0) CreateStormWindowConstructions(state);
365 :
366 771 : SetFlagForWindowConstructionWithShadeOrBlindLayer(state);
367 :
368 771 : state.dataSurfaceGeometry->CosZoneRelNorth.deallocate();
369 771 : state.dataSurfaceGeometry->SinZoneRelNorth.deallocate();
370 :
371 771 : state.dataHeatBal->CalcWindowRevealReflection = false; // Set to True in ProcessSurfaceVertices if beam solar reflection from window reveals
372 : // is requested for one or more exterior windows.
373 771 : state.dataSurface->BuildingShadingCount = 0;
374 771 : state.dataSurface->FixedShadingCount = 0;
375 771 : state.dataSurface->AttachedShadingCount = 0;
376 771 : state.dataSurface->ShadingSurfaceFirst = -1;
377 771 : state.dataSurface->ShadingSurfaceLast = -1;
378 :
379 : // Reserve space to avoid excess allocations
380 771 : state.dataSurface->AllExtSolAndShadingSurfaceList.reserve(state.dataSurface->TotSurfaces);
381 :
382 44533 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) { // Loop through all surfaces...
383 43762 : auto &thisSurface = state.dataSurface->Surface(SurfNum);
384 :
385 43762 : state.dataSurface->SurfAirSkyRadSplit(SurfNum) = std::sqrt(0.5 * (1.0 + thisSurface.CosTilt));
386 :
387 : // Set flag that determines whether a surface is a shadowing surface
388 43762 : thisSurface.IsShadowing = false;
389 86022 : if (thisSurface.Class == SurfaceClass::Shading || thisSurface.Class == SurfaceClass::Detached_F ||
390 42260 : thisSurface.Class == SurfaceClass::Detached_B) {
391 1542 : thisSurface.IsShadowing = true;
392 1542 : if (state.dataSurface->ShadingSurfaceFirst == -1) state.dataSurface->ShadingSurfaceFirst = SurfNum;
393 1542 : state.dataSurface->ShadingSurfaceLast = SurfNum;
394 : }
395 43762 : if ((thisSurface.HeatTransSurf && thisSurface.ExtSolar) || thisSurface.IsShadowing) {
396 : // Some attached shading surfaces may be true for both
397 18505 : state.dataSurface->AllExtSolAndShadingSurfaceList.push_back(SurfNum);
398 : }
399 43762 : if (thisSurface.Class == SurfaceClass::Shading) ++state.dataSurface->AttachedShadingCount;
400 43762 : if (thisSurface.Class == SurfaceClass::Detached_F) ++state.dataSurface->FixedShadingCount;
401 43762 : if (thisSurface.Class == SurfaceClass::Detached_B) ++state.dataSurface->BuildingShadingCount;
402 :
403 43762 : if (thisSurface.Class != SurfaceClass::IntMass) ProcessSurfaceVertices(state, SurfNum, ErrorsFound);
404 : }
405 :
406 5585 : for (auto &e : state.dataHeatBal->Zone) {
407 4814 : e.ExtWindowArea = 0.0;
408 4814 : e.HasWindow = false;
409 4814 : e.ExtGrossWallArea = 0.0;
410 4814 : e.ExtNetWallArea = 0.0;
411 4814 : e.TotalSurfArea = 0.0;
412 : }
413 :
414 5594 : for (auto &s : state.dataHeatBal->space) {
415 4823 : s.extWindowArea = 0.0;
416 4823 : s.totalSurfArea = 0.0;
417 : }
418 771 : DetailedWWR = (state.dataInputProcessing->inputProcessor->getNumSectionsFound("DETAILEDWWR_DEBUG") > 0);
419 771 : if (DetailedWWR) {
420 0 : print(state.files.debug, "{}", "=======User Entered Classification =================");
421 0 : print(state.files.debug, "{}", "Surface,Class,Area,Tilt");
422 : }
423 :
424 44533 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) { // Loop through all surfaces to find windows...
425 43762 : auto &thisSurface = state.dataSurface->Surface(SurfNum);
426 :
427 43762 : if (!thisSurface.HeatTransSurf && !thisSurface.IsAirBoundarySurf) continue; // Skip shadowing (sub)surfaces
428 42220 : auto &thisZone = state.dataHeatBal->Zone(thisSurface.Zone);
429 42220 : auto &thisSpace = state.dataHeatBal->space(thisSurface.spaceNum);
430 :
431 42220 : thisZone.TotalSurfArea += thisSurface.Area;
432 42220 : thisSpace.totalSurfArea += thisSurface.Area;
433 42220 : if (state.dataConstruction->Construct(thisSurface.Construction).TypeIsWindow) {
434 5976 : thisZone.TotalSurfArea += state.dataSurface->SurfWinFrameArea(SurfNum);
435 5976 : thisZone.HasWindow = true;
436 5976 : thisSpace.totalSurfArea += state.dataSurface->SurfWinFrameArea(SurfNum);
437 : }
438 42220 : if (thisSurface.Class == SurfaceClass::Roof) ZoneCeilingArea(thisSurface.Zone) += thisSurface.GrossArea;
439 42220 : if (!state.dataConstruction->Construct(thisSurface.Construction).TypeIsWindow) {
440 36244 : if (thisSurface.ExtBoundCond == ExternalEnvironment || thisSurface.ExtBoundCond == OtherSideCondModeledExt) {
441 11159 : thisZone.ExteriorTotalSurfArea += thisSurface.GrossArea;
442 11159 : thisSpace.ExteriorTotalSurfArea += thisSurface.GrossArea;
443 22318 : if (thisSurface.Class == SurfaceClass::Wall) {
444 8488 : thisZone.ExtNetWallArea += thisSurface.Area;
445 8488 : thisZone.ExtGrossWallArea += thisSurface.GrossArea;
446 8488 : thisSpace.ExtGrossWallArea += thisSurface.GrossArea;
447 8488 : thisZone.ExtGrossWallArea_Multiplied += thisSurface.GrossArea * thisZone.Multiplier * thisZone.ListMultiplier;
448 8488 : if (DetailedWWR) {
449 0 : print(state.files.debug,
450 : "{},Wall,{:.2R},{:.1R}\n",
451 : thisSurface.Name,
452 0 : thisSurface.GrossArea * thisZone.Multiplier * thisZone.ListMultiplier,
453 0 : thisSurface.Tilt);
454 : }
455 : }
456 47874 : } else if (thisSurface.ExtBoundCond == Ground || thisSurface.ExtBoundCond == GroundFCfactorMethod ||
457 22789 : thisSurface.ExtBoundCond == KivaFoundation) {
458 2334 : thisZone.ExteriorTotalGroundSurfArea += thisSurface.GrossArea;
459 2334 : if (thisSurface.Class == SurfaceClass::Wall) {
460 195 : thisZone.ExtGrossGroundWallArea += thisSurface.GrossArea;
461 195 : thisZone.ExtGrossGroundWallArea_Multiplied += thisSurface.GrossArea * thisZone.Multiplier * thisZone.ListMultiplier;
462 195 : if (DetailedWWR) {
463 0 : print(state.files.debug,
464 : "{},Wall-GroundContact,{:.2R},{:.1R}\n",
465 : thisSurface.Name,
466 0 : thisSurface.GrossArea * thisZone.Multiplier * thisZone.ListMultiplier,
467 0 : thisSurface.Tilt);
468 : }
469 : }
470 : }
471 :
472 : } else { // For Windows
473 :
474 11938 : if (((thisSurface.ExtBoundCond == ExternalEnvironment) || (thisSurface.ExtBoundCond == OtherSideCondModeledExt)) &&
475 5962 : (thisSurface.Class != SurfaceClass::TDD_Dome)) {
476 5960 : thisZone.ExtWindowArea += thisSurface.GrossArea;
477 5960 : thisSpace.extWindowArea += thisSurface.GrossArea;
478 5960 : thisZone.ExtWindowArea_Multiplied =
479 5960 : thisZone.ExtWindowArea + thisSurface.GrossArea * thisSurface.Multiplier * thisZone.Multiplier * thisZone.ListMultiplier;
480 5960 : if (DetailedWWR) {
481 0 : print(state.files.debug,
482 : "{},Window,{:.2R},{:.1R}\n",
483 : thisSurface.Name,
484 0 : thisSurface.GrossArea * thisSurface.Multiplier * thisZone.Multiplier * thisZone.ListMultiplier,
485 0 : thisSurface.Tilt);
486 : }
487 : }
488 : }
489 :
490 : } // ...end of surfaces windows DO loop
491 :
492 771 : if (DetailedWWR) {
493 0 : print(state.files.debug, "{}\n", "========================");
494 0 : print(state.files.debug, "{}\n", "Zone,ExtWallArea,ExtWindowArea");
495 : }
496 :
497 5585 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
498 4814 : auto &thisZone = state.dataHeatBal->Zone(ZoneNum);
499 9632 : for (int spaceNum : thisZone.spaceIndexes) {
500 4818 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
501 4818 : CeilCount = 0.0;
502 4818 : FloorCount = 0.0;
503 4818 : Count = 0;
504 4818 : AverageHeight = 0.0;
505 4818 : ZCeilAvg = 0.0;
506 4818 : ZFlrAvg = 0.0;
507 4818 : ZMax = -99999.0;
508 4818 : ZMin = 99999.0;
509 4818 : if (DetailedWWR) {
510 0 : print(state.files.debug, "{},{:.2R},{:.2R}\n", thisZone.Name, thisZone.ExtGrossWallArea, thisZone.ExtWindowArea);
511 : }
512 : // Use AllSurfaceFirst which includes air boundaries
513 47038 : for (int SurfNum = thisSpace.AllSurfaceFirst; SurfNum <= thisSpace.AllSurfaceLast; ++SurfNum) {
514 42220 : auto &thisSurface = state.dataSurface->Surface(SurfNum);
515 :
516 42220 : if (thisSurface.Class == SurfaceClass::Roof) {
517 : // Use Average Z for surface, more important for roofs than floors...
518 5490 : ++CeilCount;
519 5490 : Z1 = minval(thisSurface.Vertex({1, thisSurface.Sides}), &Vector::z);
520 5490 : Z2 = maxval(thisSurface.Vertex({1, thisSurface.Sides}), &Vector::z);
521 : // ZCeilAvg=ZCeilAvg+(Z1+Z2)/2.d0
522 5490 : ZCeilAvg += ((Z1 + Z2) / 2.0) * (thisSurface.GrossArea / ZoneCeilingArea(ZoneNum));
523 : }
524 42220 : if (thisSurface.Class == SurfaceClass::Floor) {
525 : // Use Average Z for surface, more important for roofs than floors...
526 6522 : ++FloorCount;
527 6522 : Z1 = minval(thisSurface.Vertex({1, thisSurface.Sides}), &Vector::z);
528 6522 : Z2 = maxval(thisSurface.Vertex({1, thisSurface.Sides}), &Vector::z);
529 : // ZFlrAvg=ZFlrAvg+(Z1+Z2)/2.d0
530 6522 : ZFlrAvg += ((Z1 + Z2) / 2.0) * (thisSurface.Area / thisZone.FloorArea);
531 : }
532 42220 : if (thisSurface.Class == SurfaceClass::Wall) {
533 : // Use Wall calculation in case no roof & floor in zone
534 21482 : ++Count;
535 21482 : if (Count == 1) {
536 4794 : ZMax = thisSurface.Vertex(1).z;
537 4794 : ZMin = ZMax;
538 : }
539 21482 : ZMax = max(ZMax, maxval(thisSurface.Vertex({1, thisSurface.Sides}), &Vector::z));
540 21482 : ZMin = min(ZMin, minval(thisSurface.Vertex({1, thisSurface.Sides}), &Vector::z));
541 : }
542 : }
543 4818 : if (CeilCount > 0.0 && FloorCount > 0.0) {
544 4812 : AverageHeight = ZCeilAvg - ZFlrAvg;
545 : } else {
546 6 : AverageHeight = (ZMax - ZMin);
547 : }
548 4818 : if (AverageHeight <= 0.0) {
549 2 : AverageHeight = (ZMax - ZMin);
550 : }
551 :
552 4818 : if (thisZone.CeilingHeight > 0.0) {
553 1754 : ZoneCeilingHeightEntered(ZoneNum) = true;
554 1754 : if (AverageHeight > 0.0) {
555 1752 : if (std::abs(AverageHeight - thisZone.CeilingHeight) / thisZone.CeilingHeight > 0.05) {
556 11 : if (ErrCount == 1 && !state.dataGlobal->DisplayExtraWarnings) {
557 0 : ShowWarningError(
558 : state,
559 0 : std::string{RoutineName} +
560 : "Entered Ceiling Height for some zone(s) significantly different from calculated Ceiling Height");
561 0 : ShowContinueError(
562 : state, "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on each max iteration exceeded.");
563 : }
564 11 : if (state.dataGlobal->DisplayExtraWarnings) {
565 0 : ShowWarningError(state,
566 0 : std::string{RoutineName} + "Entered Ceiling Height for Zone=\"" + thisZone.Name +
567 : "\" significantly different from calculated Ceiling Height");
568 : static constexpr std::string_view ValFmt("{:.2F}");
569 0 : String1 = format(ValFmt, thisZone.CeilingHeight);
570 0 : String2 = format(ValFmt, AverageHeight);
571 0 : ShowContinueError(state,
572 0 : std::string{RoutineName} + "Entered Ceiling Height=" + String1 +
573 0 : ", Calculated Ceiling Height=" + String2 + ", entered height will be used in calculations.");
574 : }
575 : }
576 : }
577 : }
578 4818 : if ((thisZone.CeilingHeight <= 0.0) && (AverageHeight > 0.0)) thisZone.CeilingHeight = AverageHeight;
579 : // Need to add check here - don't touch if already user-specified
580 : }
581 : }
582 :
583 771 : CalculateZoneVolume(state, ZoneCeilingHeightEntered); // Calculate Zone Volumes
584 :
585 : // Calculate zone centroid (and min/max x,y,z for zone)
586 : // Use AllSurfaceFirst which includes air boundaries
587 5585 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
588 4814 : auto &thisZone = state.dataHeatBal->Zone(ZoneNum);
589 4814 : nonInternalMassSurfacesPresent = false;
590 4814 : TotSurfArea = 0.0;
591 4814 : thisZone.Centroid = Vector(0.0, 0.0, 0.0);
592 4814 : if (state.dataSurface->Surface(thisZone.AllSurfaceFirst).Sides > 0) {
593 4814 : thisZone.MinimumX = state.dataSurface->Surface(thisZone.AllSurfaceFirst).Vertex(1).x;
594 4814 : thisZone.MaximumX = state.dataSurface->Surface(thisZone.AllSurfaceFirst).Vertex(1).x;
595 4814 : thisZone.MinimumY = state.dataSurface->Surface(thisZone.AllSurfaceFirst).Vertex(1).y;
596 4814 : thisZone.MaximumY = state.dataSurface->Surface(thisZone.AllSurfaceFirst).Vertex(1).y;
597 4814 : thisZone.MinimumZ = state.dataSurface->Surface(thisZone.AllSurfaceFirst).Vertex(1).z;
598 4814 : thisZone.MaximumZ = state.dataSurface->Surface(thisZone.AllSurfaceFirst).Vertex(1).z;
599 : }
600 9632 : for (int spaceNum : thisZone.spaceIndexes) {
601 4818 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
602 :
603 47038 : for (int SurfNum = thisSpace.AllSurfaceFirst; SurfNum <= thisSpace.AllSurfaceLast; ++SurfNum) {
604 42220 : auto &thisSurface = state.dataSurface->Surface(SurfNum);
605 42220 : if (thisSurface.Class == SurfaceClass::IntMass) continue;
606 39936 : nonInternalMassSurfacesPresent = true;
607 52900 : if (thisSurface.Class == SurfaceClass::Wall || (thisSurface.Class == SurfaceClass::Roof) ||
608 12964 : (thisSurface.Class == SurfaceClass::Floor)) {
609 :
610 33494 : thisZone.Centroid.x += thisSurface.Centroid.x * thisSurface.GrossArea;
611 33494 : thisZone.Centroid.y += thisSurface.Centroid.y * thisSurface.GrossArea;
612 33494 : thisZone.Centroid.z += thisSurface.Centroid.z * thisSurface.GrossArea;
613 33494 : TotSurfArea += thisSurface.GrossArea;
614 : }
615 39936 : thisZone.MinimumX = min(thisZone.MinimumX, minval(thisSurface.Vertex({1, thisSurface.Sides}), &Vector::x));
616 39936 : thisZone.MaximumX = max(thisZone.MaximumX, maxval(thisSurface.Vertex({1, thisSurface.Sides}), &Vector::x));
617 39936 : thisZone.MinimumY = min(thisZone.MinimumY, minval(thisSurface.Vertex({1, thisSurface.Sides}), &Vector::y));
618 39936 : thisZone.MaximumY = max(thisZone.MaximumY, maxval(thisSurface.Vertex({1, thisSurface.Sides}), &Vector::y));
619 39936 : thisZone.MinimumZ = min(thisZone.MinimumZ, minval(thisSurface.Vertex({1, thisSurface.Sides}), &Vector::z));
620 39936 : thisZone.MaximumZ = max(thisZone.MaximumZ, maxval(thisSurface.Vertex({1, thisSurface.Sides}), &Vector::z));
621 : }
622 : }
623 4814 : if (TotSurfArea > 0.0) {
624 4814 : thisZone.Centroid.x /= TotSurfArea;
625 4814 : thisZone.Centroid.y /= TotSurfArea;
626 4814 : thisZone.Centroid.z /= TotSurfArea;
627 : }
628 4814 : if (!nonInternalMassSurfacesPresent) {
629 0 : ShowSevereError(state,
630 0 : std::string{RoutineName} + "Zone=\"" + thisZone.Name +
631 : "\" has only internal mass surfaces. Need at least one other surface.");
632 0 : ErrorsFound = true;
633 : }
634 : }
635 :
636 771 : ZoneCeilingHeightEntered.deallocate();
637 771 : ZoneCeilingArea.deallocate();
638 :
639 771 : state.dataSurface->SurfAdjacentZone.dimension(state.dataSurface->TotSurfaces, 0);
640 : // note -- adiabatic surfaces will show same zone as surface
641 44533 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
642 43762 : if (state.dataSurface->Surface(SurfNum).ExtBoundCond <= 0) continue;
643 22732 : state.dataSurface->SurfAdjacentZone(SurfNum) = state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).ExtBoundCond).Zone;
644 : }
645 :
646 5585 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
647 1205695 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
648 1200881 : auto &thisSurface = state.dataSurface->Surface(SurfNum);
649 1200881 : if (!thisSurface.HeatTransSurf && thisSurface.ZoneName == state.dataHeatBal->Zone(ZoneNum).Name)
650 1416 : ++state.dataHeatBal->Zone(ZoneNum).NumShadingSurfaces;
651 :
652 1200881 : if (thisSurface.Zone != ZoneNum) continue;
653 :
654 84426 : if (thisSurface.HeatTransSurf &&
655 62944 : (thisSurface.Class == SurfaceClass::Wall || thisSurface.Class == SurfaceClass::Roof || thisSurface.Class == SurfaceClass::Floor))
656 33480 : ++state.dataHeatBal->Zone(ZoneNum).NumSurfaces;
657 :
658 78452 : if (thisSurface.HeatTransSurf && (thisSurface.Class == SurfaceClass::Window || thisSurface.Class == SurfaceClass::GlassDoor ||
659 107762 : thisSurface.Class == SurfaceClass::Door || thisSurface.Class == SurfaceClass::TDD_Dome ||
660 35764 : thisSurface.Class == SurfaceClass::TDD_Diffuser))
661 6442 : ++state.dataHeatBal->Zone(ZoneNum).NumSubSurfaces;
662 :
663 : } // surfaces
664 : } // zones
665 :
666 44533 : for (int const SurfNum : state.dataSurface->AllSurfaceListReportOrder) {
667 43762 : auto &thisSurface = state.dataSurface->Surface(SurfNum);
668 43762 : if (thisSurface.Construction > 0 && thisSurface.Construction <= state.dataHeatBal->TotConstructs) {
669 42220 : NominalUwithConvCoeffs = ComputeNominalUwithConvCoeffs(state, SurfNum, isWithConvCoefValid);
670 42220 : if (isWithConvCoefValid) {
671 42206 : cNominalUwithConvCoeffs = format("{:.3R}", NominalUwithConvCoeffs);
672 : } else {
673 14 : cNominalUwithConvCoeffs = "[invalid]";
674 : }
675 42220 : if ((thisSurface.Class == SurfaceClass::Window) || (thisSurface.Class == SurfaceClass::TDD_Dome)) {
676 : // SurfaceClass::Window also covers glass doors and TDD:Diffusers
677 5976 : cNominalU = "N/A";
678 : } else {
679 36244 : cNominalU = format("{:.3R}", state.dataHeatBal->NominalU(thisSurface.Construction));
680 : }
681 : } else {
682 1542 : cNominalUwithConvCoeffs = "**";
683 1542 : cNominalU = "**";
684 : }
685 :
686 : // populate the predefined report related to u-values with films
687 : // only exterior surfaces including underground
688 43762 : auto const SurfaceClass(thisSurface.Class);
689 66786 : if ((thisSurface.ExtBoundCond == ExternalEnvironment) || (thisSurface.ExtBoundCond == Ground) ||
690 46010 : (thisSurface.ExtBoundCond == KivaFoundation) || (thisSurface.ExtBoundCond == GroundFCfactorMethod)) {
691 41910 : if ((SurfaceClass == SurfaceClass::Wall) || (SurfaceClass == SurfaceClass::Floor) || (SurfaceClass == SurfaceClass::Roof)) {
692 13065 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchOpUfactFilm, thisSurface.Name, NominalUwithConvCoeffs, 3);
693 7890 : } else if (SurfaceClass == SurfaceClass::Door) {
694 386 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchDrUfactFilm, thisSurface.Name, NominalUwithConvCoeffs, 3);
695 : }
696 : } else {
697 22807 : if ((SurfaceClass == SurfaceClass::Wall) || (SurfaceClass == SurfaceClass::Floor) || (SurfaceClass == SurfaceClass::Roof)) {
698 20429 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchIntOpUfactFilm, thisSurface.Name, NominalUwithConvCoeffs, 3);
699 2378 : } else if (SurfaceClass == SurfaceClass::Door) {
700 80 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchIntDrUfactFilm, thisSurface.Name, NominalUwithConvCoeffs, 3);
701 : }
702 : }
703 : } // surfaces
704 :
705 : // Write number of shadings to initialization output file
706 771 : print(state.files.eio,
707 771 : "! <Shading Summary>, Number of Fixed Detached Shades, Number of Building Detached Shades, Number of Attached Shades\n");
708 :
709 3084 : print(state.files.eio,
710 : " Shading Summary,{},{},{}\n",
711 771 : state.dataSurface->FixedShadingCount,
712 771 : state.dataSurface->BuildingShadingCount,
713 1542 : state.dataSurface->AttachedShadingCount);
714 :
715 : // Write number of zones header to initialization output file
716 771 : print(state.files.eio, "! <Zone Summary>, Number of Zones, Number of Zone Surfaces, Number of SubSurfaces\n");
717 :
718 1542 : print(state.files.eio,
719 : " Zone Summary,{},{},{}\n",
720 771 : state.dataGlobal->NumOfZones,
721 2313 : state.dataSurface->TotSurfaces - state.dataSurface->FixedShadingCount - state.dataSurface->BuildingShadingCount -
722 771 : state.dataSurface->AttachedShadingCount,
723 2313 : sum(state.dataHeatBal->Zone, &ZoneData::NumSubSurfaces));
724 :
725 : // Write Zone Information header to the initialization output file
726 : static constexpr std::string_view Format_721(
727 : "! <Zone Information>,Zone Name,North Axis {deg},Origin X-Coordinate {m},Origin Y-Coordinate {m},Origin Z-Coordinate "
728 : "{m},Centroid X-Coordinate {m},Centroid Y-Coordinate {m},Centroid Z-Coordinate {m},Type,Zone Multiplier,Zone List "
729 : "Multiplier,Minimum X {m},Maximum X {m},Minimum Y {m},Maximum Y {m},Minimum Z {m},Maximum Z {m},Ceiling Height {m},Volume "
730 : "{m3},Zone Inside Convection Algorithm {Simple-Detailed-CeilingDiffuser-TrombeWall},Zone Outside Convection Algorithm "
731 : "{Simple-Detailed-Tarp-MoWitt-DOE-2-BLAST}, Floor Area {m2},Exterior Gross Wall Area {m2},Exterior Net Wall Area {m2},Exterior "
732 : "Window "
733 : "Area {m2}, Number of Surfaces, Number of SubSurfaces, Number of Shading SubSurfaces, Part of Total Building Area");
734 771 : print(state.files.eio, "{}\n", Format_721);
735 :
736 5585 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
737 : // Write Zone Information to the initialization output file
738 :
739 : {
740 4814 : auto const SELECT_CASE_var(state.dataHeatBal->Zone(ZoneNum).InsideConvectionAlgo);
741 4814 : if (SELECT_CASE_var == ConvectionConstants::HcInt_ASHRAESimple) {
742 1055 : String1 = "Simple";
743 3759 : } else if (SELECT_CASE_var == ConvectionConstants::HcInt_ASHRAETARP) {
744 3733 : String1 = "TARP";
745 26 : } else if (SELECT_CASE_var == ConvectionConstants::HcInt_CeilingDiffuser) {
746 10 : String1 = "CeilingDiffuser";
747 16 : } else if (SELECT_CASE_var == ConvectionConstants::HcInt_TrombeWall) {
748 1 : String1 = "TrombeWall";
749 15 : } else if (SELECT_CASE_var == ConvectionConstants::HcInt_AdaptiveConvectionAlgorithm) {
750 14 : String1 = "AdaptiveConvectionAlgorithm";
751 1 : } else if (SELECT_CASE_var == ConvectionConstants::HcInt_ASTMC1340) {
752 1 : String1 = "ASTMC1340";
753 : }
754 : }
755 :
756 : {
757 4814 : auto const SELECT_CASE_var(state.dataHeatBal->Zone(ZoneNum).OutsideConvectionAlgo);
758 4814 : if (SELECT_CASE_var == ConvectionConstants::HcExt_ASHRAESimple) {
759 1063 : String2 = "Simple";
760 3751 : } else if (SELECT_CASE_var == ConvectionConstants::HcExt_ASHRAETARP) {
761 492 : String2 = "TARP";
762 3259 : } else if (SELECT_CASE_var == ConvectionConstants::HcExt_TarpHcOutside) {
763 0 : String2 = "TARP";
764 3259 : } else if (SELECT_CASE_var == ConvectionConstants::HcExt_MoWiTTHcOutside) {
765 0 : String2 = "MoWitt";
766 3259 : } else if (SELECT_CASE_var == ConvectionConstants::HcExt_DOE2HcOutside) {
767 3243 : String2 = "DOE-2";
768 16 : } else if (SELECT_CASE_var == ConvectionConstants::HcExt_AdaptiveConvectionAlgorithm) {
769 16 : String2 = "AdaptiveConvectionAlgorithm";
770 : }
771 : }
772 :
773 4814 : if (state.dataHeatBal->Zone(ZoneNum).isPartOfTotalArea) {
774 4679 : String3 = "Yes";
775 : } else {
776 135 : String3 = "No";
777 : }
778 :
779 : static constexpr std::string_view Format_720(
780 : " Zone Information, "
781 : "{},{:.1R},{:.2R},{:.2R},{:.2R},{:.2R},{:.2R},{:.2R},{},{},{},{:.2R},{:.2R},{:.2R},{:.2R},{:.2R},{:.2R},"
782 : "{:.2R},{:.2R},{},{},{:.2R},{:.2R},{:.2R},{:.2R},{},{},{},{}\n");
783 :
784 125164 : print(state.files.eio,
785 : Format_720,
786 4814 : state.dataHeatBal->Zone(ZoneNum).Name,
787 4814 : state.dataHeatBal->Zone(ZoneNum).RelNorth,
788 4814 : state.dataHeatBal->Zone(ZoneNum).OriginX,
789 4814 : state.dataHeatBal->Zone(ZoneNum).OriginY,
790 4814 : state.dataHeatBal->Zone(ZoneNum).OriginZ,
791 4814 : state.dataHeatBal->Zone(ZoneNum).Centroid.x,
792 4814 : state.dataHeatBal->Zone(ZoneNum).Centroid.y,
793 4814 : state.dataHeatBal->Zone(ZoneNum).Centroid.z,
794 4814 : state.dataHeatBal->Zone(ZoneNum).OfType,
795 4814 : state.dataHeatBal->Zone(ZoneNum).Multiplier,
796 4814 : state.dataHeatBal->Zone(ZoneNum).ListMultiplier,
797 4814 : state.dataHeatBal->Zone(ZoneNum).MinimumX,
798 4814 : state.dataHeatBal->Zone(ZoneNum).MaximumX,
799 4814 : state.dataHeatBal->Zone(ZoneNum).MinimumY,
800 4814 : state.dataHeatBal->Zone(ZoneNum).MaximumY,
801 4814 : state.dataHeatBal->Zone(ZoneNum).MinimumZ,
802 4814 : state.dataHeatBal->Zone(ZoneNum).MaximumZ,
803 4814 : state.dataHeatBal->Zone(ZoneNum).CeilingHeight,
804 4814 : state.dataHeatBal->Zone(ZoneNum).Volume,
805 : String1,
806 : String2,
807 4814 : state.dataHeatBal->Zone(ZoneNum).FloorArea,
808 4814 : state.dataHeatBal->Zone(ZoneNum).ExtGrossWallArea,
809 4814 : state.dataHeatBal->Zone(ZoneNum).ExtNetWallArea,
810 4814 : state.dataHeatBal->Zone(ZoneNum).ExtWindowArea,
811 4814 : state.dataHeatBal->Zone(ZoneNum).NumSurfaces,
812 4814 : state.dataHeatBal->Zone(ZoneNum).NumSubSurfaces,
813 4814 : state.dataHeatBal->Zone(ZoneNum).NumShadingSurfaces,
814 : String3);
815 :
816 : } // ZoneNum
817 :
818 : // Set up solar distribution enclosures allowing for any air boundaries
819 771 : SetupEnclosuresAndAirBoundaries(state, state.dataViewFactor->EnclSolInfo, SurfaceGeometry::enclosureType::SolarEnclosures, ErrorsFound);
820 :
821 : // Do the Stratosphere check
822 771 : SetZoneOutBulbTempAt(state);
823 771 : CheckZoneOutBulbTempAt(state);
824 : }
825 :
826 771 : void AllocateSurfaceArrays(EnergyPlusData &state)
827 : {
828 :
829 : // SUBROUTINE INFORMATION:
830 : // AUTHOR Rick Strand
831 : // DATE WRITTEN February 1998
832 : // MODIFIED na
833 : // RE-ENGINEERED na
834 :
835 : // PURPOSE OF THIS SUBROUTINE:
836 : // This subroutine allocates all of the arrays at the module level which
837 : // require allocation.
838 :
839 : // METHODOLOGY EMPLOYED:
840 : // Allocation is dependent on the user input file.
841 :
842 : // REFERENCES:
843 : // na
844 :
845 : // USE STATEMENTS:
846 : // na
847 :
848 : // SUBROUTINE PARAMETER DEFINITIONS:
849 : // na
850 :
851 : // INTERFACE BLOCK SPECIFICATIONS
852 : // na
853 :
854 : // DERIVED TYPE DEFINITIONS
855 : // na
856 :
857 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
858 : // na
859 771 : state.dataSurface->ShadeV.allocate(state.dataSurface->TotSurfaces);
860 44533 : for (auto &e : state.dataSurface->ShadeV)
861 43762 : e.NVert = 0;
862 : // Individual components (XV,YV,ZV) allocated in routine ProcessSurfaceVertices
863 771 : state.dataSurface->X0.dimension(state.dataSurface->TotSurfaces, 0.0);
864 771 : state.dataSurface->Y0.dimension(state.dataSurface->TotSurfaces, 0.0);
865 771 : state.dataSurface->Z0.dimension(state.dataSurface->TotSurfaces, 0.0);
866 :
867 : // Surface EMS arrays
868 771 : state.dataSurface->SurfEMSConstructionOverrideON.allocate(state.dataSurface->TotSurfaces);
869 771 : state.dataSurface->SurfEMSConstructionOverrideValue.allocate(state.dataSurface->TotSurfaces);
870 771 : state.dataSurface->SurfEMSOverrideIntConvCoef.allocate(state.dataSurface->TotSurfaces);
871 771 : state.dataSurface->SurfEMSValueForIntConvCoef.allocate(state.dataSurface->TotSurfaces);
872 771 : state.dataSurface->SurfEMSOverrideExtConvCoef.allocate(state.dataSurface->TotSurfaces);
873 771 : state.dataSurface->SurfEMSValueForExtConvCoef.allocate(state.dataSurface->TotSurfaces);
874 771 : state.dataSurface->SurfOutDryBulbTempEMSOverrideOn.allocate(state.dataSurface->TotSurfaces);
875 771 : state.dataSurface->SurfOutDryBulbTempEMSOverrideValue.allocate(state.dataSurface->TotSurfaces);
876 771 : state.dataSurface->SurfOutWetBulbTempEMSOverrideOn.allocate(state.dataSurface->TotSurfaces);
877 771 : state.dataSurface->SurfOutWetBulbTempEMSOverrideValue.allocate(state.dataSurface->TotSurfaces);
878 771 : state.dataSurface->SurfWindSpeedEMSOverrideOn.allocate(state.dataSurface->TotSurfaces);
879 771 : state.dataSurface->SurfWindSpeedEMSOverrideValue.allocate(state.dataSurface->TotSurfaces);
880 771 : state.dataSurface->SurfViewFactorGroundEMSOverrideOn.allocate(state.dataSurface->TotSurfaces);
881 771 : state.dataSurface->SurfViewFactorGroundEMSOverrideValue.allocate(state.dataSurface->TotSurfaces);
882 771 : state.dataSurface->SurfWindDirEMSOverrideOn.allocate(state.dataSurface->TotSurfaces);
883 771 : state.dataSurface->SurfWindDirEMSOverrideValue.allocate(state.dataSurface->TotSurfaces);
884 44533 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
885 43762 : state.dataSurface->SurfEMSConstructionOverrideON(SurfNum) = false;
886 43762 : state.dataSurface->SurfEMSConstructionOverrideValue(SurfNum) = 0.0;
887 43762 : state.dataSurface->SurfEMSOverrideIntConvCoef(SurfNum) = false;
888 43762 : state.dataSurface->SurfEMSValueForIntConvCoef(SurfNum) = 0.0;
889 43762 : state.dataSurface->SurfEMSOverrideExtConvCoef(SurfNum) = false;
890 43762 : state.dataSurface->SurfEMSValueForExtConvCoef(SurfNum) = 0.0;
891 43762 : state.dataSurface->SurfOutDryBulbTempEMSOverrideOn(SurfNum) = false;
892 43762 : state.dataSurface->SurfOutDryBulbTempEMSOverrideValue(SurfNum) = 0.0;
893 43762 : state.dataSurface->SurfOutWetBulbTempEMSOverrideOn(SurfNum) = false;
894 43762 : state.dataSurface->SurfOutWetBulbTempEMSOverrideValue(SurfNum) = 0.0;
895 43762 : state.dataSurface->SurfWindSpeedEMSOverrideOn(SurfNum) = false;
896 43762 : state.dataSurface->SurfWindSpeedEMSOverrideValue(SurfNum) = 0.0;
897 43762 : state.dataSurface->SurfViewFactorGroundEMSOverrideOn(SurfNum) = false;
898 43762 : state.dataSurface->SurfViewFactorGroundEMSOverrideValue(SurfNum) = 0.0;
899 43762 : state.dataSurface->SurfWindDirEMSOverrideOn(SurfNum) = false;
900 43762 : state.dataSurface->SurfWindDirEMSOverrideValue(SurfNum) = 0.0;
901 : }
902 : // Following are surface hb arrays
903 771 : state.dataSurface->SurfOutDryBulbTemp.allocate(state.dataSurface->TotSurfaces);
904 771 : state.dataSurface->SurfOutWetBulbTemp.allocate(state.dataSurface->TotSurfaces);
905 771 : state.dataSurface->SurfOutWindSpeed.allocate(state.dataSurface->TotSurfaces);
906 771 : state.dataSurface->SurfOutWindDir.allocate(state.dataSurface->TotSurfaces);
907 771 : state.dataSurface->SurfGenericContam.allocate(state.dataSurface->TotSurfaces);
908 771 : state.dataSurface->SurfPenumbraID.allocate(state.dataSurface->TotSurfaces);
909 771 : state.dataSurface->SurfAirSkyRadSplit.allocate(state.dataSurface->TotSurfaces);
910 44533 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
911 43762 : state.dataSurface->SurfOutDryBulbTemp(SurfNum) = 0.0;
912 43762 : state.dataSurface->SurfOutWetBulbTemp(SurfNum) = 0.0;
913 43762 : state.dataSurface->SurfOutWindSpeed(SurfNum) = 0.0;
914 43762 : state.dataSurface->SurfOutWindDir(SurfNum) = 0.0;
915 43762 : state.dataSurface->SurfGenericContam(SurfNum) = 0.0;
916 43762 : state.dataSurface->SurfPenumbraID(SurfNum) = -1;
917 43762 : state.dataSurface->SurfAirSkyRadSplit(SurfNum) = 0.0;
918 : }
919 : // Following are surface property arrays used in SurfaceGeometry
920 771 : state.dataSurface->SurfShadowRecSurfNum.allocate(state.dataSurface->TotSurfaces);
921 771 : state.dataSurface->SurfShadowDisabledZoneList.allocate(state.dataSurface->TotSurfaces);
922 771 : state.dataSurface->SurfShadowDiffuseSolRefl.allocate(state.dataSurface->TotSurfaces);
923 771 : state.dataSurface->SurfShadowDiffuseVisRefl.allocate(state.dataSurface->TotSurfaces);
924 771 : state.dataSurface->SurfShadowGlazingFrac.allocate(state.dataSurface->TotSurfaces);
925 771 : state.dataSurface->SurfShadowGlazingConstruct.allocate(state.dataSurface->TotSurfaces);
926 771 : state.dataSurface->SurfMaterialMovInsulExt.allocate(state.dataSurface->TotSurfaces);
927 771 : state.dataSurface->SurfMaterialMovInsulInt.allocate(state.dataSurface->TotSurfaces);
928 771 : state.dataSurface->SurfSchedMovInsulExt.allocate(state.dataSurface->TotSurfaces);
929 771 : state.dataSurface->SurfSchedMovInsulInt.allocate(state.dataSurface->TotSurfaces);
930 44533 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
931 43762 : state.dataSurface->SurfShadowRecSurfNum(SurfNum) = 0;
932 43762 : state.dataSurface->SurfShadowDiffuseSolRefl(SurfNum) = 0.0;
933 43762 : state.dataSurface->SurfShadowDiffuseVisRefl(SurfNum) = 0.0;
934 43762 : state.dataSurface->SurfShadowGlazingFrac(SurfNum) = 0.0;
935 43762 : state.dataSurface->SurfShadowGlazingConstruct(SurfNum) = 0;
936 43762 : state.dataSurface->SurfMaterialMovInsulExt(SurfNum) = 0;
937 43762 : state.dataSurface->SurfMaterialMovInsulInt(SurfNum) = 0;
938 43762 : state.dataSurface->SurfSchedMovInsulExt(SurfNum) = 0;
939 43762 : state.dataSurface->SurfSchedMovInsulInt(SurfNum) = 0;
940 : }
941 771 : state.dataSurface->SurfExtEcoRoof.allocate(state.dataSurface->TotSurfaces);
942 771 : state.dataSurface->SurfExtCavityPresent.allocate(state.dataSurface->TotSurfaces);
943 771 : state.dataSurface->SurfExtCavNum.allocate(state.dataSurface->TotSurfaces);
944 771 : state.dataSurface->SurfIsPV.allocate(state.dataSurface->TotSurfaces);
945 771 : state.dataSurface->SurfIsICS.allocate(state.dataSurface->TotSurfaces);
946 771 : state.dataSurface->SurfIsPool.allocate(state.dataSurface->TotSurfaces);
947 771 : state.dataSurface->SurfICSPtr.allocate(state.dataSurface->TotSurfaces);
948 771 : state.dataSurface->SurfIsRadSurfOrVentSlabOrPool.allocate(state.dataSurface->TotSurfaces);
949 771 : state.dataSurface->SurfDaylightingShelfInd.allocate(state.dataSurface->TotSurfaces);
950 44533 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
951 43762 : state.dataSurface->SurfExtEcoRoof(SurfNum) = false;
952 43762 : state.dataSurface->SurfExtCavityPresent(SurfNum) = false;
953 43762 : state.dataSurface->SurfExtCavNum(SurfNum) = 0;
954 43762 : state.dataSurface->SurfIsPV(SurfNum) = false;
955 43762 : state.dataSurface->SurfIsICS(SurfNum) = false;
956 43762 : state.dataSurface->SurfIsPool(SurfNum) = false;
957 43762 : state.dataSurface->SurfICSPtr(SurfNum) = 0;
958 43762 : state.dataSurface->SurfIsRadSurfOrVentSlabOrPool(SurfNum) = false;
959 43762 : state.dataSurface->SurfDaylightingShelfInd(SurfNum) = 0;
960 : }
961 771 : state.dataSurface->SurfLowTempErrCount.allocate(state.dataSurface->TotSurfaces);
962 771 : state.dataSurface->SurfHighTempErrCount.allocate(state.dataSurface->TotSurfaces);
963 771 : state.dataSurface->SurfIntConvCoeffIndex.allocate(state.dataSurface->TotSurfaces);
964 771 : state.dataSurface->SurfExtConvCoeffIndex.allocate(state.dataSurface->TotSurfaces);
965 771 : state.dataSurface->SurfTAirRef.allocate(state.dataSurface->TotSurfaces);
966 771 : state.dataSurface->SurfTAirRefRpt.allocate(state.dataSurface->TotSurfaces);
967 771 : state.dataSurface->SurfIntConvClassification.allocate(state.dataSurface->TotSurfaces);
968 771 : state.dataSurface->SurfIntConvClassificationRpt.allocate(state.dataSurface->TotSurfaces);
969 771 : state.dataSurface->SurfIntConvHcModelEq.allocate(state.dataSurface->TotSurfaces);
970 771 : state.dataSurface->SurfIntConvHcUserCurveIndex.allocate(state.dataSurface->TotSurfaces);
971 771 : state.dataSurface->SurfOutConvClassification.allocate(state.dataSurface->TotSurfaces);
972 771 : state.dataSurface->SurfOutConvClassificationRpt.allocate(state.dataSurface->TotSurfaces);
973 771 : state.dataSurface->SurfOutConvHfModelEq.allocate(state.dataSurface->TotSurfaces);
974 771 : state.dataSurface->SurfOutConvHfUserCurveIndex.allocate(state.dataSurface->TotSurfaces);
975 771 : state.dataSurface->SurfOutConvHnModelEq.allocate(state.dataSurface->TotSurfaces);
976 771 : state.dataSurface->SurfOutConvHnUserCurveIndex.allocate(state.dataSurface->TotSurfaces);
977 771 : state.dataSurface->SurfOutConvFaceArea.allocate(state.dataSurface->TotSurfaces);
978 771 : state.dataSurface->SurfOutConvFacePerimeter.allocate(state.dataSurface->TotSurfaces);
979 771 : state.dataSurface->SurfOutConvFaceHeight.allocate(state.dataSurface->TotSurfaces);
980 771 : state.dataSurface->SurfIntConvZoneWallHeight.allocate(state.dataSurface->TotSurfaces);
981 771 : state.dataSurface->SurfIntConvZonePerimLength.allocate(state.dataSurface->TotSurfaces);
982 771 : state.dataSurface->SurfIntConvZoneHorizHydrDiam.allocate(state.dataSurface->TotSurfaces);
983 771 : state.dataSurface->SurfIntConvWindowWallRatio.allocate(state.dataSurface->TotSurfaces);
984 771 : state.dataSurface->SurfIntConvWindowLocation.allocate(state.dataSurface->TotSurfaces);
985 771 : state.dataSurface->SurfIntConvSurfGetsRadiantHeat.allocate(state.dataSurface->TotSurfaces);
986 771 : state.dataSurface->SurfIntConvSurfHasActiveInIt.allocate(state.dataSurface->TotSurfaces);
987 44533 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
988 43762 : state.dataSurface->SurfLowTempErrCount(SurfNum) = 0;
989 43762 : state.dataSurface->SurfHighTempErrCount(SurfNum) = 0;
990 43762 : state.dataSurface->SurfIntConvCoeffIndex(SurfNum) = ConvectionConstants::HcInt_SetByZone;
991 43762 : state.dataSurface->SurfExtConvCoeffIndex(SurfNum) = 0;
992 43762 : state.dataSurface->SurfTAirRef(SurfNum) = DataSurfaces::RefAirTemp::Invalid;
993 43762 : state.dataSurface->SurfTAirRefRpt(SurfNum) = static_cast<int>(DataSurfaces::RefAirTemp::Invalid);
994 43762 : state.dataSurface->SurfIntConvClassification(SurfNum) = ConvectionConstants::InConvClass::Invalid;
995 43762 : state.dataSurface->SurfIntConvClassificationRpt(SurfNum) = static_cast<int>(ConvectionConstants::InConvClass::Invalid);
996 43762 : state.dataSurface->SurfIntConvHcModelEq(SurfNum) = 0;
997 43762 : state.dataSurface->SurfIntConvHcUserCurveIndex(SurfNum) = 0;
998 43762 : state.dataSurface->SurfOutConvClassification(SurfNum) = ConvectionConstants::OutConvClass::Invalid;
999 43762 : state.dataSurface->SurfOutConvClassificationRpt(SurfNum) = static_cast<int>(ConvectionConstants::OutConvClass::Invalid);
1000 43762 : state.dataSurface->SurfOutConvHfModelEq(SurfNum) = 0;
1001 43762 : state.dataSurface->SurfOutConvHfUserCurveIndex(SurfNum) = 0;
1002 43762 : state.dataSurface->SurfOutConvHnModelEq(SurfNum) = 0;
1003 43762 : state.dataSurface->SurfOutConvHnUserCurveIndex(SurfNum) = 0;
1004 43762 : state.dataSurface->SurfOutConvFaceArea(SurfNum) = 0;
1005 43762 : state.dataSurface->SurfOutConvFacePerimeter(SurfNum) = 0;
1006 43762 : state.dataSurface->SurfOutConvFaceHeight(SurfNum) = 0;
1007 43762 : state.dataSurface->SurfIntConvZoneWallHeight(SurfNum) = 0;
1008 43762 : state.dataSurface->SurfIntConvZonePerimLength(SurfNum) = 0;
1009 43762 : state.dataSurface->SurfIntConvZoneHorizHydrDiam(SurfNum) = 0;
1010 43762 : state.dataSurface->SurfIntConvWindowWallRatio(SurfNum) = 0;
1011 43762 : state.dataSurface->SurfIntConvWindowLocation(SurfNum) = ConvectionConstants::InConvWinLoc::NotSet;
1012 43762 : state.dataSurface->SurfIntConvSurfGetsRadiantHeat(SurfNum) = false;
1013 43762 : state.dataSurface->SurfIntConvSurfHasActiveInIt(SurfNum) = false;
1014 : }
1015 771 : }
1016 :
1017 771 : void GetSurfaceData(EnergyPlusData &state, bool &ErrorsFound) // If errors found in input
1018 : {
1019 :
1020 : // SUBROUTINE INFORMATION:
1021 : // AUTHOR Richard Liesen
1022 : // DATE WRITTEN November 1997
1023 : // MODIFIED April 1999, Linda Lawrie
1024 : // Dec. 2000, FW (add "one-wall zone" checks)
1025 : // RE-ENGINEERED May 2000, Linda Lawrie (breakout surface type gets)
1026 :
1027 : // PURPOSE OF THIS SUBROUTINE:
1028 : // The purpose of this subroutine is to read in the surface information
1029 : // from the input data file and interpret and put in the derived type
1030 :
1031 : // METHODOLOGY EMPLOYED:
1032 : // The order of surfaces does not matter and the surfaces are resorted into
1033 : // the hierarchical order:
1034 : // All Shading Surfaces
1035 : // Airwalls for space x1
1036 : // Base Surfaces for space x1
1037 : // Opaque Subsurfaces for space x1
1038 : // Window Subsurfaces for space x1
1039 : // TDD Dome Surfaces for space x1
1040 : // Airwalls for space x2
1041 : // Base Surfaces for space x2
1042 : // etc
1043 : // Pointers are set in the spaces (AllSurfaceFirst/Last, HTSurfaceFirst/Last, OpaqOrIntMassSurfaceFirst/Last, WindowSurfaceFirst/Last,
1044 : // OpaqOrWinSurfaceFirst/Last, TDDDomeFirst/Last)
1045 :
1046 : // REFERENCES:
1047 : // This routine manages getting the input for the following Objects:
1048 : // SurfaceGeometry
1049 : // Surface:Shading:Detached
1050 : // Surface:HeatTransfer
1051 : // Surface:HeatTransfer:Sub
1052 : // Surface:Shading:Attached
1053 : // Surface:InternalMass
1054 :
1055 : // Vertex input:
1056 : // N3 , \field Number of Surface Vertices -- Number of (X,Y,Z) groups in this surface
1057 : // \note currently limited 3 or 4, later?
1058 : // \min 3
1059 : // \max 4
1060 : // \memo vertices are given in SurfaceGeometry coordinates -- if relative, all surface coordinates
1061 : // \memo are "relative" to the Zone Origin. if WCS, then building and zone origins are used
1062 : // \memo for some internal calculations, but all coordinates are given in an "absolute" system.
1063 : // N4, \field Vertex 1 X-coordinate
1064 : // \units m
1065 : // \type real
1066 : // N5 , \field Vertex 1 Y-coordinate
1067 : // \units m
1068 : // \type real
1069 : // N6 , \field Vertex 1 Z-coordinate
1070 : // \units m
1071 : // \type real
1072 : // N7, \field Vertex 2 X-coordinate
1073 : // \units m
1074 : // \type real
1075 : // N8, \field Vertex 2 Y-coordinate
1076 : // \units m
1077 : // \type real
1078 : // N9, \field Vertex 2 Z-coordinate
1079 : // \units m
1080 : // \type real
1081 : // N10, \field Vertex 3 X-coordinate
1082 : // \units m
1083 : // \type real
1084 : // N11, \field Vertex 3 Y-coordinate
1085 : // \units m
1086 : // \type real
1087 : // N12, \field Vertex 3 Z-coordinate
1088 : // \units m
1089 : // \type real
1090 : // N13, \field Vertex 4 X-coordinate
1091 : // \units m
1092 : // \type real
1093 : // N14, \field Vertex 4 Y-coordinate
1094 : // \type real
1095 : // \units m
1096 : // N15; \field Vertex 4 Z-coordinate
1097 : // \units m
1098 : // \type real
1099 :
1100 : // The vertices are stored in the surface derived type.
1101 : // +(1)-------------------------(4)+
1102 : // | |
1103 : // | |
1104 : // | |
1105 : // +(2)-------------------------(3)+
1106 : // The above diagram shows the actual coordinate points of a typical wall
1107 : // (you're on the outside looking toward the wall) as stored into
1108 : // Surface%Vertex(1:<number-of-sides>)
1109 :
1110 : using namespace Vectors;
1111 : using ScheduleManager::GetScheduleMaxValue;
1112 : using ScheduleManager::GetScheduleMinValue;
1113 : using namespace DataErrorTracking;
1114 :
1115 : static constexpr std::string_view RoutineName("GetSurfaceData: ");
1116 :
1117 : int ConstrNum; // Construction number
1118 : int Found; // For matching interzone surfaces
1119 : int ConstrNumFound; // Construction number of matching interzone surface
1120 771 : bool NonMatch(false); // Error for non-matching interzone surfaces
1121 : int MovedSurfs; // Number of Moved Surfaces (when sorting into hierarchical structure)
1122 771 : bool SurfError(false); // General Surface Error, causes fatal error at end of routine
1123 : int TotLay; // Total layers in a construction
1124 : int TotLayFound; // Total layers in the construction of a matching interzone surface
1125 : int TotDetachedFixed; // Total Shading:Site:Detailed entries
1126 : int TotDetachedBldg; // Total Shading:Building:Detailed entries
1127 : int TotRectDetachedFixed; // Total Shading:Site entries
1128 : int TotRectDetachedBldg; // Total Shading:Building entries
1129 : int TotHTSurfs; // Number of BuildingSurface:Detailed items to obtain
1130 : int TotDetailedWalls; // Number of Wall:Detailed items to obtain
1131 : int TotDetailedRoofs; // Number of RoofCeiling:Detailed items to obtain
1132 : int TotDetailedFloors; // Number of Floor:Detailed items to obtain
1133 : int TotHTSubs; // Number of FenestrationSurface:Detailed items to obtain
1134 : int TotShdSubs; // Number of Shading:Zone:Detailed items to obtain
1135 : int TotIntMassSurfaces; // Number of InternalMass surfaces to obtain
1136 : // Simple Surfaces (Rectangular)
1137 : int TotRectExtWalls; // Number of Exterior Walls to obtain
1138 : int TotRectIntWalls; // Number of Adiabatic Walls to obtain
1139 : int TotRectIZWalls; // Number of Interzone Walls to obtain
1140 : int TotRectUGWalls; // Number of Underground to obtain
1141 : int TotRectRoofs; // Number of Roofs to obtain
1142 : int TotRectCeilings; // Number of Adiabatic Ceilings to obtain
1143 : int TotRectIZCeilings; // Number of Interzone Ceilings to obtain
1144 : int TotRectGCFloors; // Number of Floors with Ground Contact to obtain
1145 : int TotRectIntFloors; // Number of Adiabatic Walls to obtain
1146 : int TotRectIZFloors; // Number of Interzone Floors to obtain
1147 : int TotRectWindows;
1148 : int TotRectDoors;
1149 : int TotRectGlazedDoors;
1150 : int TotRectIZWindows;
1151 : int TotRectIZDoors;
1152 : int TotRectIZGlazedDoors;
1153 : int TotOverhangs;
1154 : int TotOverhangsProjection;
1155 : int TotFins;
1156 : int TotFinsProjection;
1157 771 : bool RelWarning(false);
1158 : int ConstrNumSh; // Shaded construction number for a window
1159 : int LayNumOutside; // Outside material numbers for a shaded construction
1160 : int BlNum; // Blind number
1161 : int AddedSubSurfaces; // Subsurfaces (windows) added when windows reference Window5 Data File
1162 : // entries with two glazing systems
1163 : int NeedToAddSurfaces; // Surfaces that will be added due to "unentered" other zone surface
1164 : int NeedToAddSubSurfaces; // SubSurfaces that will be added due to "unentered" other zone surface
1165 : int CurNewSurf;
1166 : int FirstTotalSurfaces;
1167 : int NVert;
1168 : int Vert;
1169 : int n;
1170 : Real64 SurfWorldAz;
1171 : Real64 SurfTilt;
1172 :
1173 : int MultFound;
1174 : int MultSurfNum;
1175 1542 : std::string MultString;
1176 771 : auto &WarningDisplayed = state.dataSurfaceGeometry->WarningDisplayed;
1177 771 : auto &ErrCount2 = state.dataSurfaceGeometry->ErrCount2;
1178 771 : auto &ErrCount3 = state.dataSurfaceGeometry->ErrCount3;
1179 771 : auto &ErrCount4 = state.dataSurfaceGeometry->ErrCount4;
1180 : bool SubSurfaceSevereDisplayed;
1181 771 : bool subSurfaceError(false);
1182 : bool errFlag;
1183 :
1184 : int iTmp1;
1185 : int iTmp2;
1186 : // unused INTEGER :: SchID
1187 : int BlNumNew;
1188 771 : int WinShadingControlPtr(0);
1189 : int ErrCount;
1190 : bool izConstDiff; // differences in construction for IZ surfaces
1191 : bool izConstDiffMsg; // display message about hb diffs only once.
1192 :
1193 : // Get the total number of surfaces to allocate derived type and for surface loops
1194 :
1195 771 : if (state.dataSurfaceGeometry->GetSurfaceDataOneTimeFlag) {
1196 0 : return;
1197 : } else {
1198 771 : state.dataSurfaceGeometry->GetSurfaceDataOneTimeFlag = true;
1199 : }
1200 :
1201 771 : GetGeometryParameters(state, ErrorsFound);
1202 :
1203 771 : if (state.dataSurface->WorldCoordSystem) {
1204 351 : if (state.dataHeatBal->BuildingAzimuth != 0.0) RelWarning = true;
1205 1372 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
1206 1021 : if (state.dataHeatBal->Zone(ZoneNum).RelNorth != 0.0) RelWarning = true;
1207 : }
1208 351 : if (RelWarning && !WarningDisplayed) {
1209 3 : ShowWarningError(
1210 : state,
1211 2 : std::string{RoutineName} +
1212 : "World Coordinate System selected. Any non-zero Building/Zone North Axes or non-zero Zone Origins are ignored.");
1213 1 : ShowContinueError(state,
1214 : "These may be used in daylighting reference point coordinate calculations but not in normal geometry inputs.");
1215 1 : WarningDisplayed = true;
1216 : }
1217 351 : RelWarning = false;
1218 1372 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
1219 1021 : if (state.dataHeatBal->Zone(ZoneNum).OriginX != 0.0) RelWarning = true;
1220 1021 : if (state.dataHeatBal->Zone(ZoneNum).OriginY != 0.0) RelWarning = true;
1221 1021 : if (state.dataHeatBal->Zone(ZoneNum).OriginZ != 0.0) RelWarning = true;
1222 : }
1223 351 : if (RelWarning && !WarningDisplayed) {
1224 33 : ShowWarningError(
1225 : state,
1226 22 : std::string{RoutineName} +
1227 : "World Coordinate System selected. Any non-zero Building/Zone North Axes or non-zero Zone Origins are ignored.");
1228 11 : ShowContinueError(state,
1229 : "These may be used in daylighting reference point coordinate calculations but not in normal geometry inputs.");
1230 11 : WarningDisplayed = true;
1231 : }
1232 : }
1233 :
1234 771 : TotDetachedFixed = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Shading:Site:Detailed");
1235 771 : TotDetachedBldg = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Shading:Building:Detailed");
1236 771 : TotRectDetachedFixed = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Shading:Site");
1237 771 : TotRectDetachedBldg = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Shading:Building");
1238 771 : TotHTSurfs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "BuildingSurface:Detailed");
1239 771 : TotDetailedWalls = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Wall:Detailed");
1240 771 : TotDetailedRoofs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "RoofCeiling:Detailed");
1241 771 : TotDetailedFloors = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Floor:Detailed");
1242 771 : TotHTSubs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "FenestrationSurface:Detailed");
1243 771 : TotShdSubs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Shading:Zone:Detailed");
1244 771 : TotOverhangs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Shading:Overhang");
1245 771 : TotOverhangsProjection = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Shading:Overhang:Projection");
1246 771 : TotFins = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Shading:Fin");
1247 771 : TotFinsProjection = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Shading:Fin:Projection");
1248 771 : TotRectWindows = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Window");
1249 771 : TotRectDoors = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Door");
1250 771 : TotRectGlazedDoors = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "GlazedDoor");
1251 771 : TotRectIZWindows = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Window:Interzone");
1252 771 : TotRectIZDoors = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Door:Interzone");
1253 771 : TotRectIZGlazedDoors = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "GlazedDoor:Interzone");
1254 771 : TotRectExtWalls = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Wall:Exterior");
1255 771 : TotRectIntWalls = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Wall:Adiabatic");
1256 771 : TotRectIZWalls = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Wall:Interzone");
1257 771 : TotRectUGWalls = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Wall:Underground");
1258 771 : TotRectRoofs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Roof");
1259 771 : TotRectCeilings = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Ceiling:Adiabatic");
1260 771 : TotRectIZCeilings = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Ceiling:Interzone");
1261 771 : TotRectGCFloors = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Floor:GroundContact");
1262 771 : TotRectIntFloors = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Floor:Adiabatic");
1263 771 : TotRectIZFloors = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Floor:Interzone");
1264 :
1265 771 : state.dataSurface->TotOSC = 0;
1266 :
1267 771 : TotIntMassSurfaces = GetNumIntMassSurfaces(state);
1268 :
1269 1542 : state.dataSurface->TotSurfaces = (TotDetachedFixed + TotDetachedBldg + TotRectDetachedFixed + TotRectDetachedBldg) * 2 + TotHTSurfs +
1270 1542 : TotHTSubs + TotShdSubs * 2 + TotIntMassSurfaces + TotOverhangs * 2 + TotOverhangsProjection * 2 +
1271 1542 : TotFins * 4 + TotFinsProjection * 4 + TotDetailedWalls + TotDetailedRoofs + TotDetailedFloors +
1272 771 : TotRectWindows + TotRectDoors + TotRectGlazedDoors + TotRectIZWindows + TotRectIZDoors +
1273 771 : TotRectIZGlazedDoors + TotRectExtWalls + TotRectIntWalls + TotRectIZWalls + TotRectUGWalls + TotRectRoofs +
1274 771 : TotRectCeilings + TotRectIZCeilings + TotRectGCFloors + TotRectIntFloors + TotRectIZFloors;
1275 :
1276 771 : state.dataSurfaceGeometry->SurfaceTmp.allocate(state.dataSurface->TotSurfaces); // Allocate the Surface derived type appropriately
1277 771 : state.dataSurfaceGeometry->UniqueSurfaceNames.reserve(state.dataSurface->TotSurfaces);
1278 : // SurfaceTmp structure is allocated via derived type initialization.
1279 :
1280 771 : int NumSurfs = 0;
1281 771 : AddedSubSurfaces = 0;
1282 771 : state.dataErrTracking->AskForSurfacesReport = true;
1283 :
1284 771 : GetDetShdSurfaceData(state, ErrorsFound, NumSurfs, TotDetachedFixed, TotDetachedBldg);
1285 :
1286 771 : GetRectDetShdSurfaceData(state, ErrorsFound, NumSurfs, TotRectDetachedFixed, TotRectDetachedBldg);
1287 :
1288 1542 : GetHTSurfaceData(state,
1289 : ErrorsFound,
1290 : NumSurfs,
1291 : TotHTSurfs,
1292 : TotDetailedWalls,
1293 : TotDetailedRoofs,
1294 : TotDetailedFloors,
1295 771 : state.dataSurfaceGeometry->BaseSurfCls,
1296 771 : state.dataSurfaceGeometry->BaseSurfIDs,
1297 : NeedToAddSurfaces);
1298 :
1299 771 : GetRectSurfaces(state,
1300 : ErrorsFound,
1301 : NumSurfs,
1302 : TotRectExtWalls,
1303 : TotRectIntWalls,
1304 : TotRectIZWalls,
1305 : TotRectUGWalls,
1306 : TotRectRoofs,
1307 : TotRectCeilings,
1308 : TotRectIZCeilings,
1309 : TotRectGCFloors,
1310 : TotRectIntFloors,
1311 : TotRectIZFloors,
1312 771 : state.dataSurfaceGeometry->BaseSurfIDs,
1313 : NeedToAddSurfaces);
1314 :
1315 1542 : GetHTSubSurfaceData(state,
1316 : ErrorsFound,
1317 : NumSurfs,
1318 : TotHTSubs,
1319 771 : state.dataSurfaceGeometry->SubSurfCls,
1320 771 : state.dataSurfaceGeometry->SubSurfIDs,
1321 : AddedSubSurfaces,
1322 : NeedToAddSubSurfaces);
1323 :
1324 771 : GetRectSubSurfaces(state,
1325 : ErrorsFound,
1326 : NumSurfs,
1327 : TotRectWindows,
1328 : TotRectDoors,
1329 : TotRectGlazedDoors,
1330 : TotRectIZWindows,
1331 : TotRectIZDoors,
1332 : TotRectIZGlazedDoors,
1333 771 : state.dataSurfaceGeometry->SubSurfIDs,
1334 : AddedSubSurfaces,
1335 : NeedToAddSubSurfaces);
1336 :
1337 771 : GetAttShdSurfaceData(state, ErrorsFound, NumSurfs, TotShdSubs);
1338 :
1339 771 : GetSimpleShdSurfaceData(state, ErrorsFound, NumSurfs, TotOverhangs, TotOverhangsProjection, TotFins, TotFinsProjection);
1340 :
1341 771 : GetIntMassSurfaceData(state, ErrorsFound, NumSurfs);
1342 :
1343 771 : state.dataSurface->TotSurfaces = NumSurfs + AddedSubSurfaces + NeedToAddSurfaces + NeedToAddSubSurfaces;
1344 :
1345 771 : if (ErrorsFound) {
1346 0 : ShowFatalError(state, std::string{RoutineName} + "Errors discovered, program terminates.");
1347 : }
1348 :
1349 771 : state.dataSurface->Surface.allocate(state.dataSurface->TotSurfaces); // Allocate the Surface derived type appropriately
1350 771 : state.dataSurface->SurfaceWindow.allocate(state.dataSurface->TotSurfaces);
1351 771 : AllocateSurfaceArrays(state);
1352 771 : AllocateSurfaceWindows(state, state.dataSurface->TotSurfaces);
1353 :
1354 : // Have to make room for added surfaces, if needed
1355 771 : FirstTotalSurfaces = NumSurfs + AddedSubSurfaces;
1356 771 : if (NeedToAddSurfaces + NeedToAddSubSurfaces > 0) {
1357 30 : state.dataSurfaceGeometry->SurfaceTmp.redimension(state.dataSurface->TotSurfaces);
1358 : }
1359 :
1360 : // add the "need to add" surfaces
1361 : // Debug write(outputfiledebug,*) ' need to add ',NeedtoAddSurfaces+NeedToAddSubSurfaces
1362 771 : if (NeedToAddSurfaces + NeedToAddSubSurfaces > 0) CurNewSurf = FirstTotalSurfaces;
1363 44165 : for (int SurfNum = 1; SurfNum <= FirstTotalSurfaces; ++SurfNum) {
1364 43394 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond != UnenteredAdjacentZoneSurface) continue;
1365 : // Need to add surface
1366 368 : ++CurNewSurf;
1367 : // Debug write(outputfiledebug,*) ' adding surface=',curnewsurf
1368 368 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf) = state.dataSurfaceGeometry->SurfaceTmp(SurfNum);
1369 : // Basic parameters are the same for both surfaces.
1370 1104 : Found = UtilityRoutines::FindItemInList(
1371 1104 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName, state.dataHeatBal->Zone, state.dataGlobal->NumOfZones);
1372 368 : if (Found == 0) continue;
1373 368 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Zone = Found;
1374 368 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ZoneName = state.dataHeatBal->Zone(Found).Name;
1375 : // Reverse Construction
1376 368 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Construction =
1377 368 : AssignReverseConstructionNumber(state, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction, SurfError);
1378 368 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ConstructionStoredInputValue =
1379 368 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Construction;
1380 : // Reverse Vertices
1381 368 : NVert = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides;
1382 1840 : for (Vert = 1; Vert <= state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides; ++Vert) {
1383 1472 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Vertex(Vert) = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(NVert);
1384 1472 : --NVert;
1385 : }
1386 368 : if (state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Sides > 2) {
1387 736 : CreateNewellAreaVector(state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Vertex,
1388 368 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Sides,
1389 368 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).NewellAreaVector);
1390 368 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).GrossArea =
1391 368 : VecLength(state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).NewellAreaVector);
1392 368 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Area = state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).GrossArea;
1393 368 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).NetAreaShadowCalc = state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Area;
1394 736 : CreateNewellSurfaceNormalVector(state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Vertex,
1395 368 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Sides,
1396 368 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).NewellSurfaceNormalVector);
1397 2208 : DetermineAzimuthAndTilt(state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Vertex,
1398 368 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Sides,
1399 : SurfWorldAz,
1400 : SurfTilt,
1401 368 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).lcsx,
1402 368 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).lcsy,
1403 368 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).lcsz,
1404 368 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).GrossArea,
1405 368 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).NewellSurfaceNormalVector);
1406 368 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Azimuth = SurfWorldAz;
1407 368 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Tilt = SurfTilt;
1408 368 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ConvOrientation =
1409 368 : ConvectionCoefficients::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Tilt);
1410 :
1411 : // Sine and cosine of azimuth and tilt
1412 368 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).SinAzim = std::sin(SurfWorldAz * DataGlobalConstants::DegToRadians);
1413 368 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).CosAzim = std::cos(SurfWorldAz * DataGlobalConstants::DegToRadians);
1414 368 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).SinTilt = std::sin(SurfTilt * DataGlobalConstants::DegToRadians);
1415 368 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).CosTilt = std::cos(SurfTilt * DataGlobalConstants::DegToRadians);
1416 : // Outward normal unit vector (pointing away from room)
1417 736 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).OutNormVec =
1418 736 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).NewellSurfaceNormalVector;
1419 1472 : for (n = 1; n <= 3; ++n) {
1420 1104 : if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).OutNormVec(n) - 1.0) < 1.e-06)
1421 86 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).OutNormVec(n) = +1.0;
1422 1104 : if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).OutNormVec(n) + 1.0) < 1.e-06)
1423 240 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).OutNormVec(n) = -1.0;
1424 1104 : if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).OutNormVec(n)) < 1.e-06)
1425 694 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).OutNormVec(n) = 0.0;
1426 : }
1427 :
1428 : // Can perform tests on this surface here
1429 368 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ViewFactorSky =
1430 368 : 0.5 * (1.0 + state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).CosTilt);
1431 368 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ViewFactorGround =
1432 368 : 0.5 * (1.0 - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).CosTilt);
1433 :
1434 : // The following IR view factors are modified in subr. SkyDifSolarShading if there are shadowing
1435 : // surfaces
1436 368 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ViewFactorSkyIR = state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ViewFactorSky;
1437 368 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ViewFactorGroundIR =
1438 368 : 0.5 * (1.0 - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).CosTilt);
1439 : }
1440 :
1441 : // Change Name
1442 368 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Name = "iz-" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
1443 : // Debug write(outputfiledebug,*) ' new surf name=',TRIM(SurfaceTmp(CurNewSurf)%Name)
1444 : // Debug write(outputfiledebug,*) ' new surf in zone=',TRIM(surfacetmp(curnewsurf)%zoneName)
1445 368 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ExtBoundCond = UnreconciledZoneSurface;
1446 368 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = UnreconciledZoneSurface;
1447 368 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
1448 368 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Name;
1449 1009 : if (state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Class == SurfaceClass::Roof ||
1450 387 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Class == SurfaceClass::Wall ||
1451 19 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Class == SurfaceClass::Floor) {
1452 : // base surface
1453 364 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Roof) {
1454 95 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Class = SurfaceClass::Floor;
1455 : // Debug write(outputfiledebug,*) ' new surfaces is a floor'
1456 269 : } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Floor) {
1457 15 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Class = SurfaceClass::Roof;
1458 : // Debug write(outputfiledebug,*) ' new surfaces is a roof'
1459 : }
1460 364 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).BaseSurf = CurNewSurf;
1461 364 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).BaseSurfName = state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Name;
1462 : // Debug write(outputfiledebug,*) ' basesurf, extboundcondname=',TRIM(SurfaceTmp(CurNewSurf)%ExtBoundCondName)
1463 : } else {
1464 : // subsurface
1465 8 : Found = UtilityRoutines::FindItemInList("iz-" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName,
1466 4 : state.dataSurfaceGeometry->SurfaceTmp,
1467 4 : FirstTotalSurfaces + CurNewSurf - 1);
1468 4 : if (Found > 0) {
1469 8 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).BaseSurfName =
1470 12 : "iz-" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName;
1471 4 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).BaseSurf = Found;
1472 4 : state.dataSurfaceGeometry->SurfaceTmp(Found).Area -= state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Area;
1473 7 : if (state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Class == SurfaceClass::Window ||
1474 3 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Class == SurfaceClass::GlassDoor) {
1475 2 : state.dataSurfaceGeometry->SurfaceTmp(Found).NetAreaShadowCalc -=
1476 2 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Area / state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Multiplier;
1477 : } else { // Door, TDD:Diffuser, TDD:DOME
1478 2 : state.dataSurfaceGeometry->SurfaceTmp(Found).NetAreaShadowCalc -= state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Area;
1479 : }
1480 4 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ExtBoundCond = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCond;
1481 4 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
1482 4 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ExtSolar = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtSolar;
1483 4 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ExtWind = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtWind;
1484 4 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Zone = state.dataSurfaceGeometry->SurfaceTmp(Found).Zone;
1485 4 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ZoneName = state.dataSurfaceGeometry->SurfaceTmp(Found).ZoneName;
1486 4 : state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).OSCPtr = state.dataSurfaceGeometry->SurfaceTmp(Found).OSCPtr;
1487 : // Debug write(outputfiledebug,*) ' subsurf, extboundcondname=',TRIM(SurfaceTmp(CurNewSurf)%ExtBoundCondName)
1488 : // Debug write(outputfiledebug,*) ' subsurf, basesurf=',TRIM('iz-'//SurfaceTmp(SurfNum)%BaseSurfName)
1489 : } else {
1490 0 : ShowSevereError(state,
1491 0 : std::string{RoutineName} + "Adding unentered subsurface, could not find base surface=" + "iz-" +
1492 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName);
1493 0 : SurfError = true;
1494 : }
1495 : }
1496 : }
1497 : //**********************************************************************************
1498 : // After all of the surfaces have been defined then the base surfaces for the
1499 : // sub-surfaces can be defined. Loop through surfaces and match with the sub-surface
1500 : // names.
1501 44533 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
1502 43762 : if (!state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf) continue;
1503 :
1504 : // why are we doing this again? this should have already been done.
1505 42220 : if (UtilityRoutines::SameString(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName,
1506 42220 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name)) {
1507 35778 : Found = SurfNum;
1508 : } else {
1509 12884 : Found = UtilityRoutines::FindItemInList(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName,
1510 6442 : state.dataSurfaceGeometry->SurfaceTmp,
1511 6442 : state.dataSurface->TotSurfaces);
1512 : }
1513 42220 : if (Found > 0) {
1514 42220 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf = Found;
1515 42220 : if (SurfNum != Found) { // for subsurfaces
1516 6442 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf) ++state.dataSurfaceGeometry->SurfaceTmp(Found).NumSubSurfaces;
1517 12884 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class < SurfaceClass::Window ||
1518 6442 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class > SurfaceClass::TDD_Diffuser) {
1519 0 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::None) {
1520 0 : ShowSevereError(state,
1521 0 : std::string{RoutineName} +
1522 0 : "Invalid SubSurface detected, Surface=" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name);
1523 : } else {
1524 0 : ShowSevereError(state,
1525 0 : std::string{RoutineName} + "Invalid SubSurface detected, Surface=" +
1526 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + ", class=" +
1527 0 : state.dataSurfaceGeometry->BaseSurfCls(int(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class)) +
1528 : " invalid class for subsurface");
1529 0 : SurfError = true;
1530 : }
1531 : }
1532 : }
1533 : }
1534 :
1535 : } // ...end of the Surface DO loop for finding BaseSurf
1536 : //**********************************************************************************
1537 : // The surfaces need to be hierarchical by space. Input is allowed to be in any order. In
1538 : // this section the surfaces are reordered into:
1539 : // All shadowing surfaces (if mirrored, Mir- surface follows immediately after original)
1540 : // Shading:Site
1541 : // Shading:Building
1542 : // Shading:space (and variants)
1543 : // For each space:
1544 : // Walls
1545 : // Floors
1546 : // Roofs/Ceilings
1547 : // Internal Mass
1548 : // Non-Window subsurfaces (including doors)
1549 : // Window subsurfaces (including TubularDaylightingDiffusers)
1550 : // TubularDaylightingDomes
1551 : // After reordering, MovedSurfs should equal TotSurfaces
1552 :
1553 : // For reporting purposes, the legacy surface order is also saved in DataSurfaces::AllSurfaceListReportOrder:
1554 : // All shadowing surfaces (if mirrored, Mir- surface follows immediately after original)
1555 : // Shading:Site
1556 : // Shading:Building
1557 : // Shading:Zone (and variants)
1558 : // For each zone:
1559 : // Walls
1560 : // subsurfaces for each wall (windows, doors, in input order, not sorted) follow the base surface
1561 : // Floors
1562 : // subsurfaces for each floor (windows, doors, in input order, not sorted) follow the base surface
1563 : // Roofs/Ceilings
1564 : // subsurfaces for each roof/ceiling (windows, doors, in input order, not sorted) follow the base surface
1565 : // Internal Mass
1566 : // After reordering, MovedSurfs should equal TotSurfaces
1567 :
1568 771 : MovedSurfs = 0;
1569 1542 : Array1D<bool> SurfaceTmpClassMoved; // Tmp class is moved
1570 771 : SurfaceTmpClassMoved.dimension(state.dataSurface->TotSurfaces, false);
1571 771 : state.dataSurface->AllSurfaceListReportOrder.reserve(state.dataSurface->TotSurfaces);
1572 :
1573 771 : CreateMissingSpaces(state, state.dataSurfaceGeometry->SurfaceTmp);
1574 :
1575 : // Old SurfNum to New SurfNum
1576 : // Old = order in state.dataSurfaceGeometry->SurfaceTmp
1577 : // New = order in state.dataSurface->Surface
1578 1542 : EPVector<int> oldToNewSurfNums;
1579 771 : oldToNewSurfNums.resize(state.dataSurface->TotSurfaces, -1);
1580 :
1581 : // Move all shading Surfaces to Front
1582 44533 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
1583 131186 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Detached_F &&
1584 87384 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Detached_B &&
1585 43622 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Shading)
1586 42220 : continue;
1587 :
1588 : // A shading surface
1589 1542 : ++MovedSurfs;
1590 : // Store list of moved surface numbers in reporting order
1591 1542 : state.dataSurface->Surface(MovedSurfs) = state.dataSurfaceGeometry->SurfaceTmp(SurfNum);
1592 1542 : SurfaceTmpClassMoved(SurfNum) = true; //'Moved'
1593 1542 : state.dataSurface->AllSurfaceListReportOrder.push_back(SurfNum);
1594 1542 : oldToNewSurfNums(SurfNum) = MovedSurfs;
1595 : }
1596 :
1597 : // For each zone
1598 :
1599 5585 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
1600 9632 : for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
1601 : // Group air boundary surfaces first within each space
1602 1205959 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
1603 1201141 : if (SurfaceTmpClassMoved(SurfNum)) continue;
1604 617525 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).spaceNum != spaceNum) continue;
1605 42220 : int constNum = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction;
1606 42220 : if (constNum == 0) continue;
1607 42220 : if (!state.dataConstruction->Construct(constNum).TypeIsAirBoundary) continue;
1608 :
1609 : // An air boundary surface
1610 14 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).IsAirBoundarySurf = true;
1611 14 : ++MovedSurfs;
1612 14 : state.dataSurface->Surface(MovedSurfs) = state.dataSurfaceGeometry->SurfaceTmp(SurfNum);
1613 : // If base Surface Type (Wall, Floor, Roof/Ceiling)
1614 28 : if ((state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == state.dataSurfaceGeometry->BaseSurfIDs(1)) ||
1615 14 : (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == state.dataSurfaceGeometry->BaseSurfIDs(2)) ||
1616 0 : (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == state.dataSurfaceGeometry->BaseSurfIDs(3))) {
1617 : // Store list of moved surface numbers in reporting order. We use the old position, we'll reconcile later
1618 : // We don't do it for Air Door/Air Windows yet, we want them listed below each base surf they belong to
1619 14 : state.dataSurface->AllSurfaceListReportOrder.push_back(SurfNum);
1620 : }
1621 14 : oldToNewSurfNums(SurfNum) = MovedSurfs;
1622 14 : SurfaceTmpClassMoved(SurfNum) = true; //'Moved'
1623 : }
1624 :
1625 : // For each Base Surface Type (Wall, Floor, Roof/Ceiling) - put these first
1626 :
1627 19272 : for (int Loop = 1; Loop <= 3; ++Loop) {
1628 :
1629 3617877 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
1630 :
1631 3603423 : if (SurfaceTmpClassMoved(SurfNum)) continue;
1632 1803075 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone == 0) continue;
1633 :
1634 1803075 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).spaceNum != spaceNum) continue;
1635 77160 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != state.dataSurfaceGeometry->BaseSurfIDs(Loop)) continue;
1636 :
1637 33480 : ++MovedSurfs;
1638 33480 : state.dataSurface->Surface(MovedSurfs) = state.dataSurfaceGeometry->SurfaceTmp(SurfNum);
1639 33480 : oldToNewSurfNums(SurfNum) = MovedSurfs;
1640 33480 : SurfaceTmpClassMoved(SurfNum) = true; // 'Moved'
1641 : // Store list of moved surface numbers in order reporting order (subsurfaces follow their base surface)
1642 33480 : state.dataSurface->AllSurfaceListReportOrder.push_back(SurfNum);
1643 :
1644 : // Find all subsurfaces to this surface - just to update Report them in order
1645 8743378 : for (int SubSurfNum = 1; SubSurfNum <= state.dataSurface->TotSurfaces; ++SubSurfNum) {
1646 : // Gotta avoid pushing myself again!
1647 8709898 : if (SubSurfNum == SurfNum) continue;
1648 : // We don't check if already moved, because we didn't add them to AllSurfaceListReportOrder above!
1649 8676418 : if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).Zone == 0) continue;
1650 8604764 : if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).BaseSurf != SurfNum) continue;
1651 : // Add original sub-surface numbers as placeholders in surface list for reporting
1652 6442 : state.dataSurface->AllSurfaceListReportOrder.push_back(SubSurfNum);
1653 : }
1654 : }
1655 : }
1656 :
1657 : // Internal mass goes next
1658 1205959 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
1659 :
1660 1201141 : if (SurfaceTmpClassMoved(SurfNum)) continue;
1661 584031 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).spaceNum != spaceNum) continue;
1662 8726 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::IntMass) continue;
1663 2284 : ++MovedSurfs;
1664 2284 : state.dataSurface->Surface(MovedSurfs) = state.dataSurfaceGeometry->SurfaceTmp(SurfNum);
1665 2284 : oldToNewSurfNums(SurfNum) = MovedSurfs;
1666 2284 : SurfaceTmpClassMoved(SurfNum) = true; // 'Moved'
1667 : // Store list of moved surface numbers in reporting order
1668 2284 : state.dataSurface->AllSurfaceListReportOrder.push_back(SurfNum);
1669 : }
1670 :
1671 : // Opaque door goes next
1672 1205959 : for (int SubSurfNum = 1; SubSurfNum <= state.dataSurface->TotSurfaces; ++SubSurfNum) {
1673 :
1674 1201141 : if (SurfaceTmpClassMoved(SubSurfNum)) continue;
1675 581747 : if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).spaceNum != spaceNum) continue;
1676 6442 : if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).Class != SurfaceClass::Door) continue;
1677 :
1678 466 : ++MovedSurfs;
1679 466 : state.dataSurface->Surface(MovedSurfs) = state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum);
1680 466 : oldToNewSurfNums(SubSurfNum) = MovedSurfs;
1681 466 : SurfaceTmpClassMoved(SubSurfNum) = true; // 'Moved'
1682 : }
1683 :
1684 : // The exterior window subsurfaces (includes SurfaceClass::Window and SurfaceClass::GlassDoor) goes next
1685 1205959 : for (int SubSurfNum = 1; SubSurfNum <= state.dataSurface->TotSurfaces; ++SubSurfNum) {
1686 :
1687 1201141 : if (SurfaceTmpClassMoved(SubSurfNum)) continue;
1688 581281 : if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).spaceNum != spaceNum) continue;
1689 5976 : if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).ExtBoundCond > 0) continue; // Exterior window
1690 6487 : if ((state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).Class != SurfaceClass::Window) &&
1691 511 : (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).Class != SurfaceClass::GlassDoor))
1692 4 : continue;
1693 :
1694 5972 : ++MovedSurfs;
1695 5972 : state.dataSurface->Surface(MovedSurfs) = state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum);
1696 5972 : oldToNewSurfNums(SubSurfNum) = MovedSurfs;
1697 5972 : SurfaceTmpClassMoved(SubSurfNum) = true; // 'Moved'
1698 : }
1699 :
1700 : // The interior window subsurfaces (includes SurfaceClass::Window and SurfaceClass::GlassDoor) goes next
1701 1205959 : for (int SubSurfNum = 1; SubSurfNum <= state.dataSurface->TotSurfaces; ++SubSurfNum) {
1702 :
1703 1201141 : if (SurfaceTmpClassMoved(SubSurfNum)) continue;
1704 575309 : if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).spaceNum != spaceNum) continue;
1705 4 : if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).ExtBoundCond <= 0) continue;
1706 0 : if ((state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).Class != SurfaceClass::Window) &&
1707 0 : (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).Class != SurfaceClass::GlassDoor))
1708 0 : continue;
1709 :
1710 0 : ++MovedSurfs;
1711 0 : state.dataSurface->Surface(MovedSurfs) = state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum);
1712 0 : oldToNewSurfNums(SubSurfNum) = MovedSurfs;
1713 0 : SurfaceTmpClassMoved(SubSurfNum) = true; // 'Moved'
1714 : }
1715 :
1716 : // The SurfaceClass::TDD_Diffuser (OriginalClass = Window) goes next
1717 1205959 : for (int SubSurfNum = 1; SubSurfNum <= state.dataSurface->TotSurfaces; ++SubSurfNum) {
1718 :
1719 1201141 : if (SurfaceTmpClassMoved(SubSurfNum)) continue;
1720 575309 : if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).spaceNum != spaceNum) continue;
1721 4 : if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).Class != SurfaceClass::TDD_Diffuser) continue;
1722 :
1723 2 : ++MovedSurfs;
1724 2 : state.dataSurface->Surface(MovedSurfs) = state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum);
1725 2 : oldToNewSurfNums(SubSurfNum) = MovedSurfs;
1726 2 : SurfaceTmpClassMoved(SubSurfNum) = true; // 'Moved'
1727 : }
1728 :
1729 : // Last but not least, SurfaceClass::TDD_Dome
1730 1205959 : for (int SubSurfNum = 1; SubSurfNum <= state.dataSurface->TotSurfaces; ++SubSurfNum) {
1731 :
1732 1201141 : if (SurfaceTmpClassMoved(SubSurfNum)) continue;
1733 575307 : if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).spaceNum != spaceNum) continue;
1734 2 : if (state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum).Class != SurfaceClass::TDD_Dome) continue;
1735 :
1736 2 : ++MovedSurfs;
1737 2 : state.dataSurface->Surface(MovedSurfs) = state.dataSurfaceGeometry->SurfaceTmp(SubSurfNum);
1738 2 : oldToNewSurfNums(SubSurfNum) = MovedSurfs;
1739 2 : SurfaceTmpClassMoved(SubSurfNum) = true; // 'Moved'
1740 : }
1741 : }
1742 : }
1743 :
1744 : // Validity checking
1745 771 : assert(state.dataSurface->TotSurfaces == MovedSurfs);
1746 771 : assert(state.dataSurface->TotSurfaces == static_cast<int>(state.dataSurface->AllSurfaceListReportOrder.size()));
1747 771 : assert(state.dataSurface->TotSurfaces == static_cast<int>(oldToNewSurfNums.size()));
1748 :
1749 : // Assert validity of indices
1750 44533 : assert(std::find_if(state.dataSurface->AllSurfaceListReportOrder.cbegin(), state.dataSurface->AllSurfaceListReportOrder.cend(), [](int i) {
1751 : return i < 1;
1752 : }) == state.dataSurface->AllSurfaceListReportOrder.cend());
1753 :
1754 44533 : assert(std::find_if(oldToNewSurfNums.cbegin(), oldToNewSurfNums.cend(), [](int i) { return i < 1; }) == oldToNewSurfNums.cend());
1755 :
1756 771 : if (MovedSurfs != state.dataSurface->TotSurfaces) {
1757 0 : ShowSevereError(
1758 : state,
1759 0 : format("{}Reordered # of Surfaces ({}) not = Total # of Surfaces ({})", RoutineName, MovedSurfs, state.dataSurface->TotSurfaces));
1760 0 : SurfError = true;
1761 0 : for (int Loop = 1; Loop <= state.dataSurface->TotSurfaces; ++Loop) {
1762 0 : if (!SurfaceTmpClassMoved(Loop) && state.dataSurfaceGeometry->SurfaceTmp(Loop).Class == SurfaceClass::Invalid) {
1763 0 : ShowSevereError(state,
1764 0 : std::string{RoutineName} + "Error in Surface= \"" + state.dataSurfaceGeometry->SurfaceTmp(Loop).Name +
1765 0 : " indicated Zone=\"" + state.dataSurfaceGeometry->SurfaceTmp(Loop).ZoneName + "\"");
1766 : }
1767 : }
1768 0 : ShowWarningError(state,
1769 0 : std::string{RoutineName} +
1770 : "Remaining surface checks will use \"reordered number of surfaces\", not number of original surfaces");
1771 : }
1772 :
1773 : // Realign the relationship: surface to base surface
1774 44533 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
1775 43762 : auto &movedSurf = state.dataSurface->Surface(SurfNum);
1776 43762 : if (movedSurf.BaseSurf > 0) {
1777 42220 : int newBaseSurfNum = oldToNewSurfNums(movedSurf.BaseSurf);
1778 42220 : movedSurf.BaseSurf = newBaseSurfNum;
1779 :
1780 42220 : if (newBaseSurfNum < 1) {
1781 0 : ShowFatalError(
1782 : state,
1783 0 : format("{}Couldn't find the new Surface Number for surface index {} named '{}'. Looking for BaseSurf old index of {}",
1784 : RoutineName,
1785 : SurfNum,
1786 : movedSurf.Name,
1787 0 : movedSurf.BaseSurf));
1788 : }
1789 : }
1790 43762 : auto &reportOrderNum = state.dataSurface->AllSurfaceListReportOrder[SurfNum - 1];
1791 43762 : if (reportOrderNum > 0) {
1792 43762 : int newReportOrderNum = oldToNewSurfNums(reportOrderNum);
1793 43762 : reportOrderNum = newReportOrderNum;
1794 : }
1795 : }
1796 :
1797 771 : state.dataSurfaceGeometry->SurfaceTmp.deallocate(); // DeAllocate the Temp Surface derived type
1798 :
1799 771 : createSpaceSurfaceLists(state, ErrorsFound);
1800 :
1801 : // For each Base Surface Type (Wall, Floor, Roof)
1802 :
1803 3084 : for (int Loop = 1; Loop <= 3; ++Loop) {
1804 133599 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
1805 :
1806 131286 : if (state.dataSurface->Surface(SurfNum).Zone == 0) continue;
1807 :
1808 126660 : if (state.dataSurface->Surface(SurfNum).Class != state.dataSurfaceGeometry->BaseSurfIDs(Loop)) continue;
1809 :
1810 : // Find all subsurfaces to this surface
1811 8744122 : for (int SubSurfNum = 1; SubSurfNum <= state.dataSurface->TotSurfaces; ++SubSurfNum) {
1812 :
1813 8710628 : if (SurfNum == SubSurfNum) continue;
1814 8677134 : if (state.dataSurface->Surface(SubSurfNum).Zone == 0) continue;
1815 8605424 : if (state.dataSurface->Surface(SubSurfNum).BaseSurf != SurfNum) continue;
1816 :
1817 : // Check facing angle of Sub compared to base
1818 6442 : checkSubSurfAzTiltNorm(state, state.dataSurface->Surface(SurfNum), state.dataSurface->Surface(SubSurfNum), subSurfaceError);
1819 6442 : if (subSurfaceError) SurfError = true;
1820 : }
1821 : }
1822 : }
1823 :
1824 : //**********************************************************************************
1825 : // Now, match up interzone surfaces
1826 771 : NonMatch = false;
1827 771 : izConstDiffMsg = false;
1828 44533 : for (int SurfNum = 1; SurfNum <= MovedSurfs; ++SurfNum) { // TotSurfaces
1829 : // Clean up Shading Surfaces, make sure they don't go through here.
1830 43762 : if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) continue;
1831 : // If other surface, match it up
1832 : // Both interzone and "internal" surfaces have this pointer set
1833 : // Internal surfaces point to themselves, Interzone to another
1834 42220 : if (state.dataSurface->Surface(SurfNum).ExtBoundCond == UnreconciledZoneSurface) {
1835 14330 : if (not_blank(state.dataSurface->Surface(SurfNum).ExtBoundCondName)) {
1836 14330 : if (state.dataSurface->Surface(SurfNum).ExtBoundCondName == state.dataSurface->Surface(SurfNum).Name) {
1837 5886 : Found = SurfNum;
1838 : } else {
1839 25332 : Found = UtilityRoutines::FindItemInList(
1840 16888 : state.dataSurface->Surface(SurfNum).ExtBoundCondName, state.dataSurface->Surface, MovedSurfs);
1841 : }
1842 14330 : if (Found != 0) {
1843 14330 : state.dataSurface->Surface(SurfNum).ExtBoundCond = Found;
1844 : // Check that matching surface is also "OtherZoneSurface"
1845 22739 : if (state.dataSurface->Surface(Found).ExtBoundCond <= 0 &&
1846 8409 : state.dataSurface->Surface(Found).ExtBoundCond != UnreconciledZoneSurface) {
1847 0 : ShowSevereError(state, std::string{RoutineName} + "Potential \"OtherZoneSurface\" is not matched correctly:");
1848 :
1849 0 : ShowContinueError(state,
1850 0 : "Surface=" + state.dataSurface->Surface(SurfNum).Name +
1851 0 : ", Zone=" + state.dataSurface->Surface(SurfNum).ZoneName);
1852 0 : ShowContinueError(state,
1853 0 : "Nonmatched Other/InterZone Surface=" + state.dataSurface->Surface(Found).Name +
1854 0 : ", Zone=" + state.dataSurface->Surface(Found).ZoneName);
1855 0 : SurfError = true;
1856 : }
1857 : // Check that matching interzone surface has construction with reversed layers
1858 14330 : if (Found != SurfNum) { // Interzone surface
1859 : // Make sure different zones too (CR 4110)
1860 8444 : if (state.dataSurface->Surface(SurfNum).spaceNum == state.dataSurface->Surface(Found).spaceNum) {
1861 3 : ++ErrCount2;
1862 3 : if (ErrCount2 == 1 && !state.dataGlobal->DisplayExtraWarnings) {
1863 6 : ShowWarningError(state,
1864 4 : std::string{RoutineName} + "CAUTION -- Interspace surfaces are occuring in the same space(s).");
1865 2 : ShowContinueError(
1866 : state, "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on individual occurrences.");
1867 : }
1868 3 : if (state.dataGlobal->DisplayExtraWarnings) {
1869 0 : ShowWarningError(state,
1870 0 : std::string{RoutineName} + "CAUTION -- Interspace surfaces are usually in different spaces");
1871 0 : ShowContinueError(state,
1872 0 : "Surface=" + state.dataSurface->Surface(SurfNum).Name +
1873 0 : ", Space=" + state.dataHeatBal->space(state.dataSurface->Surface(SurfNum).spaceNum).Name +
1874 0 : ", Zone=" + state.dataSurface->Surface(SurfNum).ZoneName);
1875 0 : ShowContinueError(state,
1876 0 : "Surface=" + state.dataSurface->Surface(Found).Name +
1877 0 : ", Space=" + state.dataHeatBal->space(state.dataSurface->Surface(Found).spaceNum).Name +
1878 0 : ", Zone=" + state.dataSurface->Surface(Found).ZoneName);
1879 : }
1880 : }
1881 8444 : ConstrNum = state.dataSurface->Surface(SurfNum).Construction;
1882 8444 : ConstrNumFound = state.dataSurface->Surface(Found).Construction;
1883 8444 : if (ConstrNum <= 0 || ConstrNumFound <= 0) continue;
1884 8444 : if (state.dataConstruction->Construct(ConstrNum).ReverseConstructionNumLayersWarning &&
1885 0 : state.dataConstruction->Construct(ConstrNumFound).ReverseConstructionNumLayersWarning)
1886 0 : continue;
1887 8456 : if (state.dataConstruction->Construct(ConstrNum).ReverseConstructionLayersOrderWarning &&
1888 12 : state.dataConstruction->Construct(ConstrNumFound).ReverseConstructionLayersOrderWarning)
1889 12 : continue;
1890 8432 : TotLay = state.dataConstruction->Construct(ConstrNum).TotLayers;
1891 8432 : TotLayFound = state.dataConstruction->Construct(ConstrNumFound).TotLayers;
1892 8432 : if (TotLay != TotLayFound) { // Different number of layers
1893 : // match on like Uvalues (nominal)
1894 0 : if (std::abs(state.dataHeatBal->NominalU(ConstrNum) - state.dataHeatBal->NominalU(ConstrNumFound)) > 0.001) {
1895 0 : ShowSevereError(state,
1896 0 : std::string{RoutineName} + "Construction " + state.dataConstruction->Construct(ConstrNum).Name +
1897 0 : " of interzone surface " + state.dataSurface->Surface(SurfNum).Name +
1898 0 : " does not have the same number of layers as the construction " +
1899 0 : state.dataConstruction->Construct(ConstrNumFound).Name + " of adjacent surface " +
1900 0 : state.dataSurface->Surface(Found).Name);
1901 0 : if (!state.dataConstruction->Construct(ConstrNum).ReverseConstructionNumLayersWarning ||
1902 0 : !state.dataConstruction->Construct(ConstrNumFound).ReverseConstructionNumLayersWarning) {
1903 0 : ShowContinueError(state, "...this problem for this pair will not be reported again.");
1904 0 : state.dataConstruction->Construct(ConstrNum).ReverseConstructionNumLayersWarning = true;
1905 0 : state.dataConstruction->Construct(ConstrNumFound).ReverseConstructionNumLayersWarning = true;
1906 : }
1907 0 : SurfError = true;
1908 : }
1909 : } else { // Same number of layers; check for reverse layers
1910 : // check layers as number of layers is the same
1911 8432 : izConstDiff = false;
1912 : // ok if same nominal U
1913 8432 : CheckForReversedLayers(state, izConstDiff, ConstrNum, ConstrNumFound, TotLay);
1914 8434 : if (izConstDiff &&
1915 2 : std::abs(state.dataHeatBal->NominalU(ConstrNum) - state.dataHeatBal->NominalU(ConstrNumFound)) > 0.001) {
1916 0 : ShowSevereError(state,
1917 0 : std::string{RoutineName} + "Construction " + state.dataConstruction->Construct(ConstrNum).Name +
1918 0 : " of interzone surface " + state.dataSurface->Surface(SurfNum).Name +
1919 0 : " does not have the same materials in the reverse order as the construction " +
1920 0 : state.dataConstruction->Construct(ConstrNumFound).Name + " of adjacent surface " +
1921 0 : state.dataSurface->Surface(Found).Name);
1922 0 : ShowContinueError(state,
1923 : "or the properties of the reversed layers are not correct due to differing layer front and "
1924 : "back side values");
1925 0 : if (!state.dataConstruction->Construct(ConstrNum).ReverseConstructionLayersOrderWarning ||
1926 0 : !state.dataConstruction->Construct(ConstrNumFound).ReverseConstructionLayersOrderWarning) {
1927 0 : ShowContinueError(state, "...this problem for this pair will not be reported again.");
1928 0 : state.dataConstruction->Construct(ConstrNum).ReverseConstructionLayersOrderWarning = true;
1929 0 : state.dataConstruction->Construct(ConstrNumFound).ReverseConstructionLayersOrderWarning = true;
1930 : }
1931 0 : SurfError = true;
1932 8432 : } else if (izConstDiff) {
1933 6 : ShowWarningError(state,
1934 4 : std::string{RoutineName} + "Construction " + state.dataConstruction->Construct(ConstrNum).Name +
1935 6 : " of interzone surface " + state.dataSurface->Surface(SurfNum).Name +
1936 6 : " does not have the same materials in the reverse order as the construction " +
1937 6 : state.dataConstruction->Construct(ConstrNumFound).Name + " of adjacent surface " +
1938 2 : state.dataSurface->Surface(Found).Name);
1939 2 : ShowContinueError(state,
1940 : "or the properties of the reversed layers are not correct due to differing layer front and "
1941 : "back side values");
1942 6 : ShowContinueError(
1943 : state,
1944 4 : format("...but Nominal U values are similar, diff=[{:.4R}] ... simulation proceeds.",
1945 4 : std::abs(state.dataHeatBal->NominalU(ConstrNum) - state.dataHeatBal->NominalU(ConstrNumFound))));
1946 2 : if (!izConstDiffMsg) {
1947 2 : ShowContinueError(state,
1948 : "...if the two zones are expected to have significantly different temperatures, the proper "
1949 : "\"reverse\" construction should be created.");
1950 2 : izConstDiffMsg = true;
1951 : }
1952 2 : if (!state.dataConstruction->Construct(ConstrNum).ReverseConstructionLayersOrderWarning ||
1953 0 : !state.dataConstruction->Construct(ConstrNumFound).ReverseConstructionLayersOrderWarning) {
1954 2 : ShowContinueError(state, "...this problem for this pair will not be reported again.");
1955 2 : state.dataConstruction->Construct(ConstrNum).ReverseConstructionLayersOrderWarning = true;
1956 2 : state.dataConstruction->Construct(ConstrNumFound).ReverseConstructionLayersOrderWarning = true;
1957 : }
1958 : }
1959 : }
1960 :
1961 : // If significantly different areas -- this would not be good
1962 16864 : MultFound = state.dataHeatBal->Zone(state.dataSurface->Surface(Found).Zone).Multiplier *
1963 8432 : state.dataHeatBal->Zone(state.dataSurface->Surface(Found).Zone).ListMultiplier;
1964 16864 : MultSurfNum = state.dataHeatBal->Zone(state.dataSurface->Surface(SurfNum).Zone).Multiplier *
1965 8432 : state.dataHeatBal->Zone(state.dataSurface->Surface(SurfNum).Zone).ListMultiplier;
1966 8432 : if (state.dataSurface->Surface(Found).Area > 0.0) {
1967 33728 : if (std::abs((state.dataSurface->Surface(Found).Area * MultFound -
1968 16864 : state.dataSurface->Surface(SurfNum).Area * MultSurfNum) /
1969 16864 : state.dataSurface->Surface(Found).Area * MultFound) > 0.02) { // 2% difference in areas
1970 0 : ++ErrCount4;
1971 0 : if (ErrCount4 == 1 && !state.dataGlobal->DisplayExtraWarnings) {
1972 0 : ShowWarningError(state,
1973 0 : std::string{RoutineName} + "InterZone Surface Areas do not match as expected and "
1974 : "might not satisfy conservation of energy:");
1975 0 : ShowContinueError(
1976 : state, "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on individual mismatches.");
1977 : }
1978 0 : if (state.dataGlobal->DisplayExtraWarnings) {
1979 0 : ShowWarningError(state,
1980 0 : std::string{RoutineName} + "InterZone Surface Areas do not match as expected and "
1981 : "might not satisfy conservation of energy:");
1982 :
1983 0 : if (MultFound == 1 && MultSurfNum == 1) {
1984 0 : ShowContinueError(state,
1985 0 : format(" Area={:.1T} in Surface={}, Zone={}",
1986 0 : state.dataSurface->Surface(SurfNum).Area,
1987 0 : state.dataSurface->Surface(SurfNum).Name,
1988 0 : state.dataSurface->Surface(SurfNum).ZoneName));
1989 0 : ShowContinueError(state,
1990 0 : format(" Area={:.1T} in Surface={}, Zone={}",
1991 0 : state.dataSurface->Surface(Found).Area,
1992 0 : state.dataSurface->Surface(Found).Name,
1993 0 : state.dataSurface->Surface(Found).ZoneName));
1994 : } else { // Show multiplier info
1995 0 : ShowContinueError(state,
1996 0 : format(" Area={:.1T}, Multipliers={}, Total Area={:.1T} in Surface={} Zone={}",
1997 0 : state.dataSurface->Surface(SurfNum).Area,
1998 : MultSurfNum,
1999 0 : state.dataSurface->Surface(SurfNum).Area * MultSurfNum,
2000 0 : state.dataSurface->Surface(SurfNum).Name,
2001 0 : state.dataSurface->Surface(SurfNum).ZoneName));
2002 :
2003 0 : ShowContinueError(state,
2004 0 : format(" Area={:.1T}, Multipliers={}, Total Area={:.1T} in Surface={} Zone={}",
2005 0 : state.dataSurface->Surface(Found).Area,
2006 : MultFound,
2007 0 : state.dataSurface->Surface(Found).Area * MultFound,
2008 0 : state.dataSurface->Surface(Found).Name,
2009 0 : state.dataSurface->Surface(Found).ZoneName));
2010 : }
2011 : }
2012 : }
2013 : }
2014 : // Check opposites Azimuth and Tilt
2015 : // Tilt
2016 8432 : if (std::abs(std::abs(state.dataSurface->Surface(Found).Tilt + state.dataSurface->Surface(SurfNum).Tilt) - 180.0) > 1.0) {
2017 0 : ShowWarningError(state, std::string{RoutineName} + "InterZone Surface Tilts do not match as expected.");
2018 0 : ShowContinueError(state,
2019 0 : format(" Tilt={:.1T} in Surface={}, Zone={}",
2020 0 : state.dataSurface->Surface(SurfNum).Tilt,
2021 0 : state.dataSurface->Surface(SurfNum).Name,
2022 0 : state.dataSurface->Surface(SurfNum).ZoneName));
2023 0 : ShowContinueError(state,
2024 0 : format(" Tilt={:.1T} in Surface={}, Zone={}",
2025 0 : state.dataSurface->Surface(Found).Tilt,
2026 0 : state.dataSurface->Surface(Found).Name,
2027 0 : state.dataSurface->Surface(Found).ZoneName));
2028 : }
2029 : // check surface class match. interzone surface.
2030 :
2031 22458 : if ((state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Wall &&
2032 16864 : state.dataSurface->Surface(Found).Class != SurfaceClass::Wall) ||
2033 11270 : (state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Wall &&
2034 2838 : state.dataSurface->Surface(Found).Class == SurfaceClass::Wall)) {
2035 0 : ShowWarningError(state, std::string{RoutineName} + "InterZone Surface Classes do not match as expected.");
2036 0 : ShowContinueError(state,
2037 0 : "Surface=\"" + state.dataSurface->Surface(SurfNum).Name +
2038 0 : "\", surface class=" + cSurfaceClass(state.dataSurface->Surface(SurfNum).Class));
2039 0 : ShowContinueError(state,
2040 0 : "Adjacent Surface=\"" + state.dataSurface->Surface(Found).Name +
2041 0 : "\", surface class=" + cSurfaceClass(state.dataSurface->Surface(Found).Class));
2042 0 : ShowContinueError(state, "Other errors/warnings may follow about these surfaces.");
2043 : }
2044 18257 : if ((state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Roof &&
2045 16864 : state.dataSurface->Surface(Found).Class != SurfaceClass::Floor) ||
2046 15471 : (state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Roof &&
2047 7039 : state.dataSurface->Surface(Found).Class == SurfaceClass::Floor)) {
2048 0 : ShowWarningError(state, std::string{RoutineName} + "InterZone Surface Classes do not match as expected.");
2049 0 : ShowContinueError(state,
2050 0 : "Surface=\"" + state.dataSurface->Surface(SurfNum).Name +
2051 0 : "\", surface class=" + cSurfaceClass(state.dataSurface->Surface(SurfNum).Class));
2052 0 : ShowContinueError(state,
2053 0 : "Adjacent Surface=\"" + state.dataSurface->Surface(Found).Name +
2054 0 : "\", surface class=" + cSurfaceClass(state.dataSurface->Surface(Found).Class));
2055 0 : ShowContinueError(state, "Other errors/warnings may follow about these surfaces.");
2056 : }
2057 15471 : if (state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Roof &&
2058 7039 : state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Floor) {
2059 : // Walls, Windows, Doors, Glass Doors
2060 5634 : if (state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Wall) {
2061 : // Surface is a Door, Window or Glass Door
2062 40 : if (state.dataSurface->Surface(SurfNum).BaseSurf == 0) continue; // error detected elsewhere
2063 79 : if (state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).Class == SurfaceClass::Roof ||
2064 39 : state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).Class == SurfaceClass::Floor)
2065 2 : continue;
2066 : }
2067 11264 : if (std::abs(std::abs(state.dataSurface->Surface(SurfNum).Azimuth - state.dataSurface->Surface(Found).Azimuth) -
2068 5632 : 180.0) > 1.0) {
2069 0 : if (std::abs(state.dataSurface->Surface(SurfNum).SinTilt) > 0.5 || state.dataGlobal->DisplayExtraWarnings) {
2070 : // if horizontal surfaces, then these are windows/doors/etc in those items.
2071 0 : ShowWarningError(state, std::string{RoutineName} + "InterZone Surface Azimuths do not match as expected.");
2072 0 : ShowContinueError(state,
2073 0 : format(" Azimuth={:.1T}, Tilt={:.1T}, in Surface={}, Zone={}",
2074 0 : state.dataSurface->Surface(SurfNum).Azimuth,
2075 0 : state.dataSurface->Surface(SurfNum).Tilt,
2076 0 : state.dataSurface->Surface(SurfNum).Name,
2077 0 : state.dataSurface->Surface(SurfNum).ZoneName));
2078 0 : ShowContinueError(state,
2079 0 : format(" Azimuth={:.1T}, Tilt={:.1T}, in Surface={}, Zone={}",
2080 0 : state.dataSurface->Surface(Found).Azimuth,
2081 0 : state.dataSurface->Surface(Found).Tilt,
2082 0 : state.dataSurface->Surface(Found).Name,
2083 0 : state.dataSurface->Surface(Found).ZoneName));
2084 0 : ShowContinueError(
2085 0 : state, "..surface class of first surface=" + cSurfaceClass(state.dataSurface->Surface(SurfNum).Class));
2086 0 : ShowContinueError(
2087 0 : state, "..surface class of second surface=" + cSurfaceClass(state.dataSurface->Surface(Found).Class));
2088 : }
2089 : }
2090 : }
2091 :
2092 : // Make sure exposures (Sun, Wind) are the same.....and are "not"
2093 8430 : if (state.dataSurface->Surface(SurfNum).ExtSolar || state.dataSurface->Surface(Found).ExtSolar) {
2094 0 : ShowWarningError(state,
2095 0 : std::string{RoutineName} + "Interzone surfaces cannot be \"SunExposed\" -- removing SunExposed");
2096 0 : ShowContinueError(state,
2097 0 : " Surface=" + state.dataSurface->Surface(SurfNum).Name +
2098 0 : ", Zone=" + state.dataSurface->Surface(SurfNum).ZoneName);
2099 0 : ShowContinueError(state,
2100 0 : " Surface=" + state.dataSurface->Surface(Found).Name +
2101 0 : ", Zone=" + state.dataSurface->Surface(Found).ZoneName);
2102 0 : state.dataSurface->Surface(SurfNum).ExtSolar = false;
2103 0 : state.dataSurface->Surface(Found).ExtSolar = false;
2104 : }
2105 8430 : if (state.dataSurface->Surface(SurfNum).ExtWind || state.dataSurface->Surface(Found).ExtWind) {
2106 0 : ShowWarningError(state,
2107 0 : std::string{RoutineName} + "Interzone surfaces cannot be \"WindExposed\" -- removing WindExposed");
2108 0 : ShowContinueError(state,
2109 0 : " Surface=" + state.dataSurface->Surface(SurfNum).Name +
2110 0 : ", Zone=" + state.dataSurface->Surface(SurfNum).ZoneName);
2111 0 : ShowContinueError(state,
2112 0 : " Surface=" + state.dataSurface->Surface(Found).Name +
2113 0 : ", Zone=" + state.dataSurface->Surface(Found).ZoneName);
2114 0 : state.dataSurface->Surface(SurfNum).ExtWind = false;
2115 0 : state.dataSurface->Surface(Found).ExtWind = false;
2116 : }
2117 : }
2118 : // Set opposing surface back to this one (regardless of error)
2119 14316 : state.dataSurface->Surface(Found).ExtBoundCond = SurfNum;
2120 : // Check subsurfaces... make sure base surface is also an interzone surface
2121 14316 : if (state.dataSurface->Surface(SurfNum).BaseSurf != SurfNum) { // Subsurface
2122 76 : if ((state.dataSurface->Surface(SurfNum).ExtBoundCond != SurfNum) &&
2123 38 : not_blank(state.dataSurface->Surface(SurfNum).ExtBoundCondName)) {
2124 : // if not internal subsurface
2125 76 : if (state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond ==
2126 38 : state.dataSurface->Surface(SurfNum).BaseSurf) {
2127 : // base surface is not interzone surface
2128 0 : ShowSevereError(state,
2129 0 : std::string{RoutineName} + "SubSurface=\"" + state.dataSurface->Surface(SurfNum).Name +
2130 : "\" is an interzone subsurface.");
2131 0 : ShowContinueError(state,
2132 0 : "..but the Base Surface is not an interzone surface, Surface=\"" +
2133 0 : state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).Name + "\".");
2134 0 : SurfError = true;
2135 : }
2136 : }
2137 : }
2138 : } else {
2139 : // Seems unlikely that an internal surface would be missing itself, so this message
2140 : // only indicates for adjacent (interzone) surfaces.
2141 0 : ShowSevereError(state,
2142 0 : std::string{RoutineName} +
2143 0 : "Adjacent Surface not found: " + state.dataSurface->Surface(SurfNum).ExtBoundCondName +
2144 0 : " adjacent to surface " + state.dataSurface->Surface(SurfNum).Name);
2145 0 : NonMatch = true;
2146 0 : SurfError = true;
2147 : }
2148 0 : } else if (state.dataSurface->Surface(SurfNum).BaseSurf != SurfNum) { // Subsurface
2149 0 : if (state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond > 0 &&
2150 0 : state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond !=
2151 0 : state.dataSurface->Surface(SurfNum).BaseSurf) { // If Interzone surface, subsurface must be also.
2152 0 : ShowSevereError(state, std::string{RoutineName} + "SubSurface on Interzone Surface must be an Interzone SubSurface.");
2153 0 : ShowContinueError(state, "...OutsideFaceEnvironment is blank, in Surface=" + state.dataSurface->Surface(SurfNum).Name);
2154 0 : SurfError = true;
2155 : } else {
2156 0 : ++ErrCount3;
2157 0 : if (ErrCount3 == 1 && !state.dataGlobal->DisplayExtraWarnings) {
2158 0 : ShowWarningError(state, std::string{RoutineName} + "Blank name for Outside Boundary Condition Objects.");
2159 0 : ShowContinueError(state, "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on individual surfaces.");
2160 : }
2161 0 : if (state.dataGlobal->DisplayExtraWarnings) {
2162 0 : ShowWarningError(state,
2163 0 : std::string{RoutineName} + "Blank name for Outside Boundary Condition Object, in surface=" +
2164 0 : state.dataSurface->Surface(SurfNum).Name);
2165 0 : ShowContinueError(
2166 0 : state, "Resetting this surface to be an internal zone surface, zone=" + state.dataSurface->Surface(SurfNum).ZoneName);
2167 : }
2168 0 : state.dataSurface->Surface(SurfNum).ExtBoundCondName = state.dataSurface->Surface(SurfNum).Name;
2169 0 : state.dataSurface->Surface(SurfNum).ExtBoundCond = SurfNum;
2170 : }
2171 : } else {
2172 0 : ++ErrCount3;
2173 0 : if (ErrCount3 == 1 && !state.dataGlobal->DisplayExtraWarnings) {
2174 0 : ShowSevereError(state, std::string{RoutineName} + "Blank name for Outside Boundary Condition Objects.");
2175 0 : ShowContinueError(state, "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on individual surfaces.");
2176 : }
2177 0 : if (state.dataGlobal->DisplayExtraWarnings) {
2178 0 : ShowWarningError(state,
2179 0 : std::string{RoutineName} + "Blank name for Outside Boundary Condition Object, in surface=" +
2180 0 : state.dataSurface->Surface(SurfNum).Name);
2181 0 : ShowContinueError(state,
2182 0 : "Resetting this surface to be an internal zone (adiabatic) surface, zone=" +
2183 0 : state.dataSurface->Surface(SurfNum).ZoneName);
2184 : }
2185 0 : state.dataSurface->Surface(SurfNum).ExtBoundCondName = state.dataSurface->Surface(SurfNum).Name;
2186 0 : state.dataSurface->Surface(SurfNum).ExtBoundCond = SurfNum;
2187 0 : SurfError = true;
2188 : }
2189 : }
2190 :
2191 : } // ...end of the Surface DO loop for finding BaseSurf
2192 771 : if (NonMatch) {
2193 0 : ShowSevereError(state, std::string{RoutineName} + "Non matching interzone surfaces found");
2194 : }
2195 :
2196 : //**********************************************************************************
2197 : // Warn about interzone surfaces that have adiabatic windows/vice versa
2198 771 : SubSurfaceSevereDisplayed = false;
2199 44533 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
2200 43762 : if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) continue;
2201 42220 : if (state.dataSurface->Surface(SurfNum).BaseSurf == SurfNum) continue; // base surface
2202 : // not base surface. Check it.
2203 6442 : if (state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond <= 0) { // exterior or other base surface
2204 12724 : if (state.dataSurface->Surface(SurfNum).ExtBoundCond !=
2205 6362 : state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond) { // should match base surface
2206 0 : if (state.dataSurface->Surface(SurfNum).ExtBoundCond == SurfNum) {
2207 0 : ShowSevereError(
2208 : state,
2209 0 : std::string{RoutineName} + "Subsurface=\"" + state.dataSurface->Surface(SurfNum).Name +
2210 0 : "\" exterior condition [adiabatic surface] in a base surface=\"" +
2211 0 : state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).Name + "\" with exterior condition [" +
2212 0 : cExtBoundCondition(state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond) + ']');
2213 0 : SurfError = true;
2214 0 : } else if (state.dataSurface->Surface(SurfNum).ExtBoundCond > 0) {
2215 0 : ShowSevereError(
2216 : state,
2217 0 : std::string{RoutineName} + "Subsurface=\"" + state.dataSurface->Surface(SurfNum).Name +
2218 0 : "\" exterior condition [interzone surface] in a base surface=\"" +
2219 0 : state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).Name + "\" with exterior condition [" +
2220 0 : cExtBoundCondition(state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond) + ']');
2221 0 : SurfError = true;
2222 0 : } else if (state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond == OtherSideCondModeledExt) {
2223 0 : ShowWarningError(
2224 : state,
2225 0 : std::string{RoutineName} + "Subsurface=\"" + state.dataSurface->Surface(SurfNum).Name + "\" exterior condition [" +
2226 0 : cExtBoundCondition(state.dataSurface->Surface(SurfNum).ExtBoundCond) + "] in a base surface=\"" +
2227 0 : state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).Name + "\" with exterior condition [" +
2228 0 : cExtBoundCondition(state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond) + ']');
2229 0 : ShowContinueError(state, "...SubSurface will not use the exterior condition model of the base surface.");
2230 : } else {
2231 0 : ShowSevereError(
2232 : state,
2233 0 : std::string{RoutineName} + "Subsurface=\"" + state.dataSurface->Surface(SurfNum).Name + "\" exterior condition [" +
2234 0 : cExtBoundCondition(state.dataSurface->Surface(SurfNum).ExtBoundCond) + "] in a base surface=\"" +
2235 0 : state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).Name + "\" with exterior condition [" +
2236 0 : cExtBoundCondition(state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond) + ']');
2237 0 : SurfError = true;
2238 : }
2239 0 : if (!SubSurfaceSevereDisplayed && SurfError) {
2240 0 : ShowContinueError(state, "...calculations for heat balance would be compromised.");
2241 0 : SubSurfaceSevereDisplayed = true;
2242 : }
2243 : }
2244 160 : } else if (state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).BaseSurf ==
2245 80 : state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond) {
2246 : // adiabatic surface. make sure subsurfaces match
2247 0 : if (state.dataSurface->Surface(SurfNum).ExtBoundCond != SurfNum) { // not adiabatic surface
2248 0 : if (state.dataSurface->Surface(SurfNum).ExtBoundCond > 0) {
2249 0 : ShowSevereError(state,
2250 0 : std::string{RoutineName} + "Subsurface=\"" + state.dataSurface->Surface(SurfNum).Name +
2251 0 : "\" exterior condition [interzone surface] in a base surface=\"" +
2252 0 : state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).Name +
2253 : "\" with exterior condition [adiabatic surface]");
2254 : } else {
2255 0 : ShowSevereError(state,
2256 0 : std::string{RoutineName} + "Subsurface=\"" + state.dataSurface->Surface(SurfNum).Name +
2257 0 : "\" exterior condition [" + cExtBoundCondition(state.dataSurface->Surface(SurfNum).ExtBoundCond) +
2258 0 : "] in a base surface=\"" + state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).Name +
2259 : "\" with exterior condition [adiabatic surface]");
2260 : }
2261 0 : if (!SubSurfaceSevereDisplayed) {
2262 0 : ShowContinueError(state, "...calculations for heat balance would be compromised.");
2263 0 : SubSurfaceSevereDisplayed = true;
2264 : }
2265 0 : SurfError = true;
2266 : }
2267 80 : } else if (state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).ExtBoundCond > 0) { // interzone surface
2268 80 : if (state.dataSurface->Surface(SurfNum).ExtBoundCond == SurfNum) {
2269 0 : ShowSevereError(state,
2270 0 : std::string{RoutineName} + "Subsurface=\"" + state.dataSurface->Surface(SurfNum).Name +
2271 0 : "\" is an adiabatic surface in an Interzone base surface=\"" +
2272 0 : state.dataSurface->Surface(state.dataSurface->Surface(SurfNum).BaseSurf).Name + "\"");
2273 0 : if (!SubSurfaceSevereDisplayed) {
2274 0 : ShowContinueError(state, "...calculations for heat balance would be compromised.");
2275 0 : SubSurfaceSevereDisplayed = true;
2276 : }
2277 : // SurfError=.TRUE.
2278 : }
2279 : }
2280 : }
2281 :
2282 : //**********************************************************************************
2283 : // Set up Zone Surface Pointers
2284 5585 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
2285 9632 : for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
2286 4818 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
2287 1205945 : for (int SurfNum = 1; SurfNum <= MovedSurfs; ++SurfNum) { // TotSurfaces
2288 1201128 : if (state.dataSurface->Surface(SurfNum).spaceNum == spaceNum) {
2289 42219 : if (thisSpace.AllSurfaceFirst == 0) {
2290 4818 : thisSpace.AllSurfaceFirst = SurfNum;
2291 : }
2292 42233 : if (state.dataSurface->Surface(SurfNum).IsAirBoundarySurf) {
2293 14 : state.dataSurface->Surface(SurfNum).HeatTransSurf = false;
2294 14 : continue;
2295 : }
2296 42205 : if (thisSpace.HTSurfaceFirst == 0) {
2297 4818 : thisSpace.HTSurfaceFirst = SurfNum;
2298 : // Non window surfaces are grouped next within each zone
2299 4818 : thisSpace.OpaqOrIntMassSurfaceFirst = SurfNum;
2300 : }
2301 84426 : if ((thisSpace.WindowSurfaceFirst == 0) &&
2302 75502 : ((state.dataSurface->Surface(SurfNum).Class == DataSurfaces::SurfaceClass::Window) ||
2303 72508 : (state.dataSurface->Surface(SurfNum).Class == DataSurfaces::SurfaceClass::GlassDoor) ||
2304 36232 : (state.dataSurface->Surface(SurfNum).Class == DataSurfaces::SurfaceClass::TDD_Diffuser))) {
2305 : // Window surfaces are grouped last within each zone
2306 2995 : thisSpace.WindowSurfaceFirst = SurfNum;
2307 2995 : thisSpace.OpaqOrIntMassSurfaceLast = SurfNum - 1;
2308 : }
2309 42205 : if ((thisSpace.TDDDomeFirst == 0) && (state.dataSurface->Surface(SurfNum).Class == DataSurfaces::SurfaceClass::TDD_Dome)) {
2310 : // Window surfaces are grouped last within each zone
2311 1 : thisSpace.TDDDomeFirst = SurfNum;
2312 1 : if (thisSpace.WindowSurfaceFirst != 0) {
2313 0 : thisSpace.WindowSurfaceLast = SurfNum - 1;
2314 : } else {
2315 : // No window in the zone.
2316 1 : thisSpace.OpaqOrIntMassSurfaceLast = SurfNum - 1;
2317 1 : thisSpace.WindowSurfaceLast = -1;
2318 : }
2319 1 : break;
2320 : }
2321 : }
2322 : }
2323 : }
2324 4814 : int firstSpaceNum = state.dataHeatBal->Zone(ZoneNum).spaceIndexes(1);
2325 4814 : state.dataHeatBal->Zone(ZoneNum).AllSurfaceFirst = state.dataHeatBal->space(firstSpaceNum).AllSurfaceFirst;
2326 : }
2327 : // Surface First pointers are set, set last
2328 771 : if (state.dataGlobal->NumOfZones > 0) {
2329 741 : state.dataHeatBal->Zone(state.dataGlobal->NumOfZones).AllSurfaceLast = state.dataSurface->TotSurfaces;
2330 741 : int lastSpaceNum = state.dataHeatBal->Zone(state.dataGlobal->NumOfZones)
2331 741 : .spaceIndexes(state.dataHeatBal->Zone(state.dataGlobal->NumOfZones).spaceIndexes.size());
2332 741 : state.dataHeatBal->space(lastSpaceNum).AllSurfaceLast = state.dataSurface->TotSurfaces;
2333 : }
2334 5585 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
2335 4814 : if (ZoneNum < state.dataGlobal->NumOfZones) {
2336 4073 : state.dataHeatBal->Zone(ZoneNum).AllSurfaceLast = state.dataHeatBal->Zone(ZoneNum + 1).AllSurfaceFirst - 1;
2337 : }
2338 4814 : auto &thisSpaceList = state.dataHeatBal->Zone(ZoneNum).spaceIndexes;
2339 4814 : int numSpacesInZone = thisSpaceList.size();
2340 4814 : if (numSpacesInZone > 1) {
2341 6 : for (int spaceCount = 1; spaceCount <= numSpacesInZone - 1; ++spaceCount) {
2342 4 : auto &thisSpace = state.dataHeatBal->space(thisSpaceList(spaceCount));
2343 4 : auto &nextSpace = state.dataHeatBal->space(thisSpaceList(spaceCount + 1));
2344 4 : thisSpace.AllSurfaceLast = nextSpace.AllSurfaceFirst - 1;
2345 : }
2346 2 : state.dataHeatBal->space(thisSpaceList(numSpacesInZone)).AllSurfaceLast = state.dataHeatBal->Zone(ZoneNum).AllSurfaceLast;
2347 4812 : } else if (numSpacesInZone == 1) {
2348 4812 : auto &thisSpace = state.dataHeatBal->space(thisSpaceList(numSpacesInZone));
2349 4812 : thisSpace.AllSurfaceFirst = state.dataHeatBal->Zone(ZoneNum).AllSurfaceFirst;
2350 4812 : thisSpace.AllSurfaceLast = state.dataHeatBal->Zone(ZoneNum).AllSurfaceLast;
2351 : }
2352 : }
2353 5585 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
2354 9632 : for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
2355 4818 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
2356 4818 : if (state.dataSurface->Surface(thisSpace.AllSurfaceLast).Class == DataSurfaces::SurfaceClass::TDD_Dome) {
2357 1 : thisSpace.TDDDomeLast = thisSpace.AllSurfaceLast;
2358 11907 : } else if ((state.dataSurface->Surface(thisSpace.AllSurfaceLast).Class == DataSurfaces::SurfaceClass::Window) ||
2359 6640 : (state.dataSurface->Surface(thisSpace.AllSurfaceLast).Class == DataSurfaces::SurfaceClass::GlassDoor) ||
2360 1823 : (state.dataSurface->Surface(thisSpace.AllSurfaceLast).Class == DataSurfaces::SurfaceClass::TDD_Diffuser)) {
2361 2995 : thisSpace.TDDDomeLast = -1;
2362 2995 : thisSpace.WindowSurfaceLast = thisSpace.AllSurfaceLast;
2363 : } else {
2364 : // If there are no windows in the zone, then set this to -1 so any for loops on WindowSurfaceFirst to WindowSurfaceLast
2365 : // will not execute. Same for TDDDome and its indices
2366 1822 : thisSpace.TDDDomeLast = -1;
2367 1822 : thisSpace.WindowSurfaceLast = -1;
2368 1822 : thisSpace.OpaqOrIntMassSurfaceLast = thisSpace.AllSurfaceLast;
2369 : }
2370 4818 : thisSpace.OpaqOrWinSurfaceFirst = thisSpace.HTSurfaceFirst;
2371 4818 : thisSpace.OpaqOrWinSurfaceLast = std::max(thisSpace.OpaqOrIntMassSurfaceLast, thisSpace.WindowSurfaceLast);
2372 4818 : thisSpace.HTSurfaceLast = thisSpace.AllSurfaceLast;
2373 : }
2374 : }
2375 :
2376 5585 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
2377 4814 : int zoneSurfCount = 0;
2378 9632 : for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
2379 4818 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
2380 4818 : if (thisSpace.HTSurfaceFirst > 0) {
2381 4818 : zoneSurfCount += (thisSpace.HTSurfaceLast - thisSpace.HTSurfaceFirst + 1);
2382 : }
2383 4818 : if (zoneSurfCount == 0) {
2384 0 : ShowSevereError(state,
2385 0 : std::string{RoutineName} + "Zone has no heat transfer surfaces, Zone=" + state.dataHeatBal->Zone(ZoneNum).Name);
2386 0 : SurfError = true;
2387 : }
2388 : }
2389 : }
2390 :
2391 : // Set up Floor Areas for Zones and Spaces
2392 771 : Real64 constexpr floorAreaTolerance(0.05);
2393 771 : Real64 constexpr floorAreaPercentTolerance(floorAreaTolerance * 100.0);
2394 771 : if (!SurfError) {
2395 5585 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
2396 4814 : auto &thisZone = state.dataHeatBal->Zone(ZoneNum);
2397 9632 : for (int spaceNum : thisZone.spaceIndexes) {
2398 4818 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
2399 47024 : for (int SurfNum = thisSpace.HTSurfaceFirst; SurfNum <= thisSpace.HTSurfaceLast; ++SurfNum) {
2400 42206 : auto &thisSurf = state.dataSurface->Surface(SurfNum);
2401 42206 : if (thisSurf.Class == SurfaceClass::Floor) {
2402 6522 : thisZone.HasFloor = true;
2403 6522 : state.dataHeatBal->space(spaceNum).calcFloorArea += thisSurf.Area;
2404 : }
2405 42206 : if (thisSurf.Class == SurfaceClass::Roof) {
2406 5490 : thisZone.CeilingArea += thisSurf.Area;
2407 5490 : thisZone.HasRoof = true;
2408 : }
2409 : }
2410 : }
2411 : }
2412 771 : ErrCount = 0;
2413 5589 : for (int spaceNum = 1; spaceNum <= state.dataGlobal->numSpaces; ++spaceNum) {
2414 4818 : if (state.dataHeatBal->space(spaceNum).userEnteredFloorArea != DataGlobalConstants::AutoCalculate) {
2415 : // Check entered vs calculated
2416 0 : if (state.dataHeatBal->space(spaceNum).userEnteredFloorArea > 0.0) { // User entered Space floor area,
2417 : // produce message if not near calculated
2418 0 : if (state.dataHeatBal->space(spaceNum).calcFloorArea > 0.0) {
2419 : Real64 diffp =
2420 0 : std::abs(state.dataHeatBal->space(spaceNum).calcFloorArea - state.dataHeatBal->space(spaceNum).userEnteredFloorArea) /
2421 0 : state.dataHeatBal->space(spaceNum).userEnteredFloorArea;
2422 0 : if (diffp > floorAreaTolerance) {
2423 0 : ++ErrCount;
2424 0 : if (ErrCount == 1 && !state.dataGlobal->DisplayExtraWarnings) {
2425 0 : ShowWarningError(
2426 : state,
2427 0 : format("{}Entered Space Floor Area(s) differ more than {:.0R}% from calculated Space Floor Area(s).",
2428 0 : std::string(RoutineName),
2429 0 : floorAreaPercentTolerance));
2430 0 : ShowContinueError(state,
2431 : "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on individual Spaces.");
2432 : }
2433 0 : if (state.dataGlobal->DisplayExtraWarnings) {
2434 : // Warn user of using specified Space Floor Area
2435 0 : ShowWarningError(
2436 : state,
2437 0 : format("{}Entered Floor Area for Space=\"{}\" is {:.1R}% different from the calculated Floor Area.",
2438 0 : std::string(RoutineName),
2439 0 : state.dataHeatBal->space(spaceNum).Name,
2440 0 : diffp * 100.0));
2441 0 : ShowContinueError(state,
2442 0 : format("Entered Space Floor Area={:.2R}, Calculated Space Floor Area={:.2R}, entered "
2443 : "Floor Area will be used.",
2444 0 : state.dataHeatBal->space(spaceNum).userEnteredFloorArea,
2445 0 : state.dataHeatBal->space(spaceNum).calcFloorArea));
2446 : }
2447 : }
2448 : }
2449 0 : state.dataHeatBal->space(spaceNum).floorArea = state.dataHeatBal->space(spaceNum).userEnteredFloorArea;
2450 0 : state.dataHeatBal->space(spaceNum).hasFloor = true;
2451 : }
2452 : } else {
2453 4818 : state.dataHeatBal->space(spaceNum).floorArea = state.dataHeatBal->space(spaceNum).calcFloorArea;
2454 : }
2455 : }
2456 771 : ErrCount = 0;
2457 5585 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
2458 : // Calculate zone floor area as sum of space floor areas
2459 9632 : for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
2460 4818 : state.dataHeatBal->Zone(ZoneNum).CalcFloorArea += state.dataHeatBal->space(spaceNum).floorArea;
2461 : }
2462 4814 : if (state.dataHeatBal->Zone(ZoneNum).UserEnteredFloorArea != DataGlobalConstants::AutoCalculate) {
2463 : // Check entered vs calculated
2464 4 : if (state.dataHeatBal->Zone(ZoneNum).UserEnteredFloorArea > 0.0) { // User entered zone floor area,
2465 : // produce message if not near calculated
2466 4 : if (state.dataHeatBal->Zone(ZoneNum).CalcFloorArea > 0.0) {
2467 : Real64 diffp =
2468 4 : std::abs(state.dataHeatBal->Zone(ZoneNum).CalcFloorArea - state.dataHeatBal->Zone(ZoneNum).UserEnteredFloorArea) /
2469 4 : state.dataHeatBal->Zone(ZoneNum).UserEnteredFloorArea;
2470 4 : if (diffp > 0.05) {
2471 1 : ++ErrCount;
2472 1 : if (ErrCount == 1 && !state.dataGlobal->DisplayExtraWarnings) {
2473 3 : ShowWarningError(
2474 : state,
2475 2 : format("{}Entered Zone Floor Area(s) differ more than {:.0R}% from the sum of the Space Floor Area(s).",
2476 2 : std::string(RoutineName),
2477 1 : floorAreaPercentTolerance));
2478 1 : ShowContinueError(state,
2479 : "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on individual zones.");
2480 : }
2481 1 : if (state.dataGlobal->DisplayExtraWarnings) {
2482 : // Warn user of using specified Zone Floor Area
2483 0 : ShowWarningError(state,
2484 0 : format("{}Entered Floor Area for Zone=\"{}\" is {:.1R}% different from the sum of the "
2485 : "Space Floor Area(s).",
2486 0 : std::string(RoutineName),
2487 0 : state.dataHeatBal->Zone(ZoneNum).Name,
2488 0 : diffp * 100.0));
2489 0 : ShowContinueError(state,
2490 0 : format("Entered Zone Floor Area={:.2R}, Sum of Space Floor Area(s)={:.2R}",
2491 0 : state.dataHeatBal->Zone(ZoneNum).UserEnteredFloorArea,
2492 0 : state.dataHeatBal->Zone(ZoneNum).CalcFloorArea));
2493 0 : ShowContinueError(
2494 : state, "Entered Zone Floor Area will be used and Space Floor Area(s) will be adjusted proportionately.");
2495 : }
2496 : }
2497 : }
2498 4 : state.dataHeatBal->Zone(ZoneNum).FloorArea = state.dataHeatBal->Zone(ZoneNum).UserEnteredFloorArea;
2499 4 : state.dataHeatBal->Zone(ZoneNum).HasFloor = true;
2500 :
2501 : // Adjust space floor areas to match zone floor area
2502 4 : if (state.dataHeatBal->Zone(ZoneNum).numSpaces == 1) {
2503 : // If the zone contains only one space, then set the Space area to the Zone area
2504 4 : int spaceNum = state.dataHeatBal->Zone(ZoneNum).spaceIndexes(1);
2505 4 : state.dataHeatBal->space(spaceNum).floorArea = state.dataHeatBal->Zone(ZoneNum).FloorArea;
2506 0 : } else if (state.dataHeatBal->Zone(ZoneNum).CalcFloorArea > 0.0) {
2507 : // Adjust space areas proportionately
2508 0 : Real64 areaRatio = state.dataHeatBal->Zone(ZoneNum).FloorArea / state.dataHeatBal->Zone(ZoneNum).CalcFloorArea;
2509 0 : for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
2510 0 : state.dataHeatBal->space(spaceNum).floorArea *= areaRatio;
2511 : }
2512 : } else {
2513 0 : if (state.dataGlobal->DisplayExtraWarnings) {
2514 : // Warn if calculated floor area was zero and there is more than one Space
2515 0 : ShowWarningError(state,
2516 0 : std::string{RoutineName} + "Entered Floor Area entered for Zone=\"" +
2517 0 : state.dataHeatBal->Zone(ZoneNum).Name +
2518 : "\" significantly different from sum of Space Floor Areas");
2519 0 : ShowContinueError(state,
2520 : "But the sum of the Space Floor Areas is zero and there is more than one Space in the zone."
2521 : "Unable to apportion the zone floor area. Space Floor Areas are zero.");
2522 : }
2523 : }
2524 : } else {
2525 0 : if (state.dataHeatBal->Zone(ZoneNum).CalcFloorArea > 0.0)
2526 0 : state.dataHeatBal->Zone(ZoneNum).FloorArea = state.dataHeatBal->Zone(ZoneNum).CalcFloorArea;
2527 : }
2528 : } else {
2529 4810 : state.dataHeatBal->Zone(ZoneNum).FloorArea = state.dataHeatBal->Zone(ZoneNum).CalcFloorArea;
2530 : }
2531 4814 : Real64 totSpacesFloorArea = 0.0;
2532 9632 : for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
2533 4818 : totSpacesFloorArea += state.dataHeatBal->space(spaceNum).floorArea;
2534 : }
2535 4814 : if (totSpacesFloorArea > 0.0) {
2536 9628 : for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
2537 4816 : state.dataHeatBal->space(spaceNum).fracZoneFloorArea = state.dataHeatBal->space(spaceNum).floorArea / totSpacesFloorArea;
2538 : }
2539 : } // else leave fractions at zero
2540 : }
2541 : }
2542 :
2543 44533 : for (int SurfNum = 1; SurfNum <= MovedSurfs; ++SurfNum) { // TotSurfaces
2544 43762 : if (state.dataSurface->Surface(SurfNum).Area < 1.e-06) {
2545 0 : ShowSevereError(state,
2546 0 : format("{}Zero or negative surface area[{:.5R}], Surface={}",
2547 : RoutineName,
2548 0 : state.dataSurface->Surface(SurfNum).Area,
2549 0 : state.dataSurface->Surface(SurfNum).Name));
2550 0 : SurfError = true;
2551 : }
2552 43762 : if (state.dataSurface->Surface(SurfNum).Area >= 1.e-06 && state.dataSurface->Surface(SurfNum).Area < 0.001) {
2553 0 : ShowWarningError(state,
2554 0 : format("{}Very small surface area[{:.5R}], Surface={}",
2555 : RoutineName,
2556 0 : state.dataSurface->Surface(SurfNum).Area,
2557 0 : state.dataSurface->Surface(SurfNum).Name));
2558 : }
2559 : }
2560 :
2561 44533 : for (int SurfNum = 1; SurfNum <= MovedSurfs; ++SurfNum) { // TotSurfaces
2562 : // GLASSDOORs and TDD:DIFFUSERs will be treated as windows in the subsequent heat transfer and daylighting
2563 : // calculations. Reset class to 'Window' after saving the original designation in SurfaceWindow.
2564 :
2565 43762 : state.dataSurface->SurfWinOriginalClass(SurfNum) = state.dataSurface->Surface(SurfNum).Class;
2566 :
2567 87017 : if (state.dataSurface->Surface(SurfNum).Class == SurfaceClass::GlassDoor ||
2568 43255 : state.dataSurface->Surface(SurfNum).Class == SurfaceClass::TDD_Diffuser)
2569 509 : state.dataSurface->Surface(SurfNum).Class = SurfaceClass::Window;
2570 :
2571 43762 : if (state.dataSurface->Surface(SurfNum).Class == SurfaceClass::TDD_Dome) {
2572 : // Reset the TDD:DOME subsurface to act as a base surface that can shade and be shaded
2573 : // NOTE: This must be set early so that subsequent shading calculations are done correctly
2574 2 : state.dataSurface->Surface(SurfNum).BaseSurf = SurfNum;
2575 : }
2576 : }
2577 :
2578 771 : errFlag = false;
2579 771 : if (!SurfError) {
2580 44533 : for (int SurfNum = 1; SurfNum <= MovedSurfs; ++SurfNum) { // TotSurfaces
2581 43762 : if (state.dataSurface->Surface(SurfNum).HasShadeControl) {
2582 143 : WinShadingControlPtr =
2583 143 : state.dataSurface->Surface(SurfNum).activeWindowShadingControl; // use first item since others should be identical
2584 143 : if (state.dataSurface->WindowShadingControl(WinShadingControlPtr).slatAngleControl != SlatAngleControl::Fixed) {
2585 3 : state.dataSurface->SurfWinMovableSlats(SurfNum) = true;
2586 3 : state.dataSurface->AnyMovableSlat = true;
2587 3 : state.dataHeatBalSurf->SurfMovSlatsIndexList.push_back(SurfNum);
2588 : }
2589 :
2590 143 : ConstrNumSh = state.dataSurface->Surface(SurfNum).activeShadedConstruction;
2591 143 : if (ConstrNumSh <= 0) continue;
2592 :
2593 143 : WinShadingType ShadingType = state.dataSurface->WindowShadingControl(WinShadingControlPtr).ShadingType;
2594 :
2595 : // only for blinds
2596 143 : if (ANY_BLIND(ShadingType)) {
2597 :
2598 : // TH 1/7/2010. CR 7930
2599 : // The old code did not consider between-glass blind. Also there should not be two blinds - both interior and exterior
2600 : // Use the new generic code (assuming only one blind) as follows
2601 75 : for (iTmp1 = 1; iTmp1 <= state.dataConstruction->Construct(ConstrNumSh).TotLayers; ++iTmp1) {
2602 75 : iTmp2 = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(iTmp1);
2603 75 : if (state.dataMaterial->Material(iTmp2).Group == DataHeatBalance::MaterialGroup::WindowBlind) {
2604 34 : BlNum = state.dataMaterial->Material(iTmp2).BlindDataPtr;
2605 34 : state.dataSurface->SurfWinBlindNumber(SurfNum) = BlNum;
2606 : // TH 2/18/2010. CR 8010
2607 : // if it is a blind with movable slats, create one new blind and set it to VariableSlat if not done so yet.
2608 : // the new blind is created only once, it can be shared by multiple windows though.
2609 37 : if (state.dataSurface->SurfWinMovableSlats(SurfNum) &&
2610 3 : state.dataHeatBal->Blind(BlNum).SlatAngleType != DataWindowEquivalentLayer::AngleType::Variable) {
2611 3 : errFlag = false;
2612 3 : AddVariableSlatBlind(state, BlNum, BlNumNew, errFlag);
2613 : // point to the new blind
2614 3 : state.dataMaterial->Material(iTmp2).BlindDataPtr = BlNumNew;
2615 : // window surface points to new blind
2616 3 : state.dataSurface->SurfWinBlindNumber(SurfNum) = BlNumNew;
2617 : }
2618 34 : break;
2619 : }
2620 : }
2621 :
2622 34 : if (errFlag) {
2623 0 : ErrorsFound = true;
2624 0 : ShowContinueError(state,
2625 0 : "WindowShadingControl " + state.dataSurface->WindowShadingControl(WinShadingControlPtr).Name +
2626 : " has errors, program will terminate.");
2627 : }
2628 : }
2629 : } // End of surface loop
2630 :
2631 : // final associate fenestration surfaces referenced in WindowShadingControl
2632 43762 : FinalAssociateWindowShadingControlFenestration(state, ErrorsFound);
2633 43762 : CheckWindowShadingControlSimilarForWindow(state, ErrorsFound);
2634 : }
2635 :
2636 : // Check for zones with not enough surfaces
2637 5585 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
2638 4814 : int OpaqueHTSurfs = 0; // Number of floors, walls and roofs in a zone
2639 4814 : int OpaqueHTSurfsWithWin = 0; // Number of floors, walls and roofs with windows in a zone
2640 4814 : int InternalMassSurfs = 0; // Number of internal mass surfaces in a zone
2641 4814 : int priorBaseSurfNum = 0;
2642 :
2643 9632 : for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
2644 4818 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
2645 4818 : if (thisSpace.HTSurfaceFirst == 0) continue; // Zone with no surfaces
2646 47024 : for (int SurfNum = thisSpace.HTSurfaceFirst; SurfNum <= thisSpace.HTSurfaceLast; ++SurfNum) {
2647 42206 : auto &thisSurf = state.dataSurface->Surface(SurfNum);
2648 42206 : if (thisSurf.Class == SurfaceClass::Floor || thisSurf.Class == SurfaceClass::Wall || thisSurf.Class == SurfaceClass::Roof)
2649 33480 : ++OpaqueHTSurfs;
2650 42206 : if (thisSurf.Class == SurfaceClass::IntMass) ++InternalMassSurfs;
2651 42206 : if (thisSurf.Class == SurfaceClass::Window) {
2652 : // Count base surface only once for multiple windows on a wall
2653 5974 : int thisBaseSurfNum = thisSurf.BaseSurf;
2654 5974 : if (thisBaseSurfNum != priorBaseSurfNum) {
2655 3934 : ++OpaqueHTSurfsWithWin;
2656 3934 : priorBaseSurfNum = thisBaseSurfNum;
2657 : }
2658 : }
2659 : }
2660 : }
2661 4814 : if (OpaqueHTSurfsWithWin == 1 && OpaqueHTSurfs == 1 && InternalMassSurfs == 0) {
2662 0 : SurfError = true;
2663 0 : ShowSevereError(state,
2664 0 : std::string{RoutineName} + "Zone " + state.dataHeatBal->Zone(ZoneNum).Name +
2665 : " has only one floor, wall or roof, and this surface has a window.");
2666 0 : ShowContinueError(state, "Add more floors, walls or roofs, or an internal mass surface.");
2667 : }
2668 : }
2669 :
2670 : // set up vertex of centroid for each surface.
2671 771 : CalcSurfaceCentroid(state);
2672 :
2673 771 : SetupShadeSurfacesForSolarCalcs(state); // if shading surfaces are solar collectors or PV, then we need full solar calc.
2674 :
2675 771 : GetMovableInsulationData(state, ErrorsFound);
2676 :
2677 771 : if (state.dataSurface->CalcSolRefl) GetShadingSurfReflectanceData(state, ErrorsFound);
2678 :
2679 771 : LayNumOutside = 0;
2680 44533 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
2681 : // Check for EcoRoof and only 1 allowed to be used.
2682 43762 : if (state.dataSurface->Surface(SurfNum).Construction > 0)
2683 42220 : state.dataSurface->SurfExtEcoRoof(SurfNum) =
2684 42220 : state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).TypeIsEcoRoof;
2685 43762 : if (!state.dataSurface->SurfExtEcoRoof(SurfNum)) continue;
2686 24 : if (LayNumOutside == 0) {
2687 4 : LayNumOutside = state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).LayerPoint(1);
2688 4 : continue;
2689 : }
2690 16 : if (LayNumOutside != state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).LayerPoint(1)) {
2691 0 : ShowSevereError(state, std::string{RoutineName} + "Only one EcoRoof Material is currently allowed for all constructions.");
2692 0 : ShowContinueError(state, "... first material=" + state.dataMaterial->Material(LayNumOutside).Name);
2693 0 : ShowContinueError(
2694 : state,
2695 0 : "... conflicting Construction=" + state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).Name +
2696 0 : " uses material=" +
2697 : state.dataMaterial
2698 0 : ->Material(state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).LayerPoint(1))
2699 : .Name);
2700 0 : ErrorsFound = true;
2701 : }
2702 : }
2703 :
2704 : // Reserve space to avoid excess allocations
2705 771 : state.dataSurface->AllHTSurfaceList.reserve(state.dataSurface->TotSurfaces);
2706 771 : state.dataSurface->AllExtSolarSurfaceList.reserve(state.dataSurface->TotSurfaces);
2707 771 : state.dataSurface->AllShadowPossObstrSurfaceList.reserve(state.dataSurface->TotSurfaces);
2708 771 : state.dataSurface->AllIZSurfaceList.reserve(state.dataSurface->TotSurfaces);
2709 771 : state.dataSurface->AllHTNonWindowSurfaceList.reserve(state.dataSurface->TotSurfaces - state.dataSurface->TotWindows);
2710 771 : state.dataSurface->AllHTWindowSurfaceList.reserve(state.dataSurface->TotWindows);
2711 771 : state.dataSurface->AllExtSolWindowSurfaceList.reserve(state.dataSurface->TotWindows);
2712 771 : state.dataSurface->AllExtSolWinWithFrameSurfaceList.reserve(state.dataSurface->TotWindows);
2713 771 : state.dataSurface->AllHTKivaSurfaceList.reserve(state.dataSurface->TotSurfaces);
2714 :
2715 : // Set flag that determines whether a surface can be an exterior obstruction
2716 : // Also set associated surfaces for Kiva foundations and build heat transfer surface lists
2717 44533 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
2718 43762 : state.dataSurface->Surface(SurfNum).IsShadowPossibleObstruction = false;
2719 43762 : if (state.dataSurface->Surface(SurfNum).ExtSolar) {
2720 : // This may include some attached shading surfaces
2721 18381 : state.dataSurface->AllExtSolarSurfaceList.push_back(SurfNum);
2722 : }
2723 43762 : if (state.dataSurface->Surface(SurfNum).HeatTransSurf) {
2724 : // Outside light shelves get tagged later as HeatTransSurf=true but they haven't been processed yet
2725 42206 : state.dataSurface->AllHTSurfaceList.push_back(SurfNum);
2726 42206 : int const zoneNum(state.dataSurface->Surface(SurfNum).Zone);
2727 42206 : auto &surfZone(state.dataHeatBal->Zone(zoneNum));
2728 42206 : surfZone.ZoneHTSurfaceList.push_back(SurfNum);
2729 : // Sort window vs non-window surfaces
2730 42206 : if (state.dataSurface->Surface(SurfNum).Class == DataSurfaces::SurfaceClass::Window) {
2731 5974 : state.dataSurface->AllHTWindowSurfaceList.push_back(SurfNum);
2732 5974 : surfZone.ZoneHTWindowSurfaceList.push_back(SurfNum);
2733 5974 : if (state.dataSurface->Surface(SurfNum).ExtSolar) {
2734 5958 : state.dataSurface->AllExtSolWindowSurfaceList.push_back(SurfNum);
2735 5958 : if (state.dataSurface->Surface(SurfNum).FrameDivider > 0) {
2736 381 : state.dataSurface->AllExtSolWinWithFrameSurfaceList.push_back(SurfNum);
2737 : }
2738 : }
2739 : } else {
2740 36232 : state.dataSurface->AllHTNonWindowSurfaceList.push_back(SurfNum);
2741 36232 : surfZone.ZoneHTNonWindowSurfaceList.push_back(SurfNum);
2742 : }
2743 42206 : int const surfExtBoundCond(state.dataSurface->Surface(SurfNum).ExtBoundCond);
2744 : // Build zone and interzone surface lists
2745 42206 : if ((surfExtBoundCond > 0) && (surfExtBoundCond != SurfNum)) {
2746 16844 : state.dataSurface->AllIZSurfaceList.push_back(SurfNum);
2747 16844 : surfZone.ZoneIZSurfaceList.push_back(SurfNum);
2748 16844 : auto &adjZone(state.dataHeatBal->Zone(state.dataSurface->Surface(surfExtBoundCond).Zone));
2749 16844 : adjZone.ZoneHTSurfaceList.push_back(SurfNum);
2750 16844 : adjZone.ZoneIZSurfaceList.push_back(SurfNum);
2751 : // Sort window vs non-window surfaces
2752 16844 : if (state.dataSurface->Surface(SurfNum).Class == DataSurfaces::SurfaceClass::Window) {
2753 14 : adjZone.ZoneHTWindowSurfaceList.push_back(SurfNum);
2754 : } else {
2755 16830 : adjZone.ZoneHTNonWindowSurfaceList.push_back(SurfNum);
2756 : }
2757 : }
2758 : }
2759 : // Exclude non-exterior heat transfer surfaces (but not OtherSideCondModeledExt = -4 CR7640)
2760 43762 : if (state.dataSurface->Surface(SurfNum).HeatTransSurf && state.dataSurface->Surface(SurfNum).ExtBoundCond > 0) continue;
2761 21044 : if (state.dataSurface->Surface(SurfNum).HeatTransSurf && state.dataSurface->Surface(SurfNum).ExtBoundCond == Ground) continue;
2762 18965 : if (state.dataSurface->Surface(SurfNum).HeatTransSurf && state.dataSurface->Surface(SurfNum).ExtBoundCond == KivaFoundation) {
2763 38 : state.dataSurface->AllHTKivaSurfaceList.push_back(SurfNum);
2764 38 : if (!ErrorsFound)
2765 38 : state.dataSurfaceGeometry->kivaManager.foundationInputs[state.dataSurface->Surface(SurfNum).OSCPtr].surfaces.push_back(
2766 : SurfNum);
2767 38 : continue;
2768 : }
2769 18889 : if (state.dataSurface->Surface(SurfNum).HeatTransSurf && state.dataSurface->Surface(SurfNum).ExtBoundCond == OtherSideCoefNoCalcExt)
2770 32 : continue;
2771 18857 : if (state.dataSurface->Surface(SurfNum).HeatTransSurf && state.dataSurface->Surface(SurfNum).ExtBoundCond == OtherSideCoefCalcExt)
2772 1 : continue;
2773 : // Exclude windows and doors, i.e., consider only their base surfaces as possible obstructions
2774 31752 : if (state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Window ||
2775 12896 : state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Door)
2776 6345 : continue;
2777 : // Exclude duplicate shading surfaces
2778 12511 : if (state.dataSurface->Surface(SurfNum).MirroredSurf) continue;
2779 : // Exclude air boundary surfaces
2780 11740 : if (state.dataSurface->Surface(SurfNum).IsAirBoundarySurf) continue;
2781 :
2782 11726 : state.dataSurface->Surface(SurfNum).IsShadowPossibleObstruction = true;
2783 11726 : state.dataSurface->AllShadowPossObstrSurfaceList.push_back(SurfNum);
2784 : }
2785 :
2786 : // Check for IRT surfaces in invalid places.
2787 771 : iTmp1 = 0;
2788 771 : if (std::any_of(state.dataConstruction->Construct.begin(),
2789 771 : state.dataConstruction->Construct.end(),
2790 5843 : [](Construction::ConstructionProps const &e) { return e.TypeIsIRT; })) {
2791 76 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
2792 74 : if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) continue; // ignore shading surfaces
2793 74 : if (state.dataSurface->Surface(SurfNum).ExtBoundCond > 0 && state.dataSurface->Surface(SurfNum).ExtBoundCond != SurfNum)
2794 28 : continue; // interzone, not adiabatic surface
2795 46 : if (!state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).TypeIsIRT) {
2796 46 : continue;
2797 : }
2798 0 : if (!state.dataGlobal->DisplayExtraWarnings) {
2799 0 : ++iTmp1;
2800 : } else {
2801 0 : ShowWarningError(state,
2802 0 : std::string{RoutineName} + "Surface=\"" + state.dataSurface->Surface(SurfNum).Name +
2803 : "\" uses InfraredTransparent construction in a non-interzone surface. (illegal use)");
2804 : }
2805 : }
2806 2 : if (iTmp1 > 0) {
2807 0 : ShowWarningError(
2808 : state,
2809 0 : format("{}Surfaces use InfraredTransparent constructions {} in non-interzone surfaces. (illegal use)", RoutineName, iTmp1));
2810 0 : ShowContinueError(state, "For explicit details on each use, use Output:Diagnostics,DisplayExtraWarnings;");
2811 : }
2812 : }
2813 :
2814 : // Note, could do same for Window Area and detecting if Interzone Surface in Zone
2815 :
2816 771 : if (state.dataSurfaceGeometry->Warning1Count > 0) {
2817 15 : ShowWarningMessage(state,
2818 15 : format("{}Window dimensions differ from Window 5/6 data file dimensions, {} times.",
2819 : RoutineName,
2820 10 : state.dataSurfaceGeometry->Warning1Count));
2821 5 : ShowContinueError(state, "This will affect the frame heat transfer calculation if the frame in the Data File entry");
2822 5 : ShowContinueError(state, "is not uniform, i.e., has sections with different geometry and/or thermal properties.");
2823 5 : ShowContinueError(state, "For explicit details on each window, use Output:Diagnostics,DisplayExtraWarnings;");
2824 : }
2825 771 : if (state.dataSurfaceGeometry->Warning2Count > 0) {
2826 0 : ShowWarningMessage(state,
2827 0 : format("{}Exterior Windows have been replaced with Window 5/6 two glazing systems, {} times.",
2828 : RoutineName,
2829 0 : state.dataSurfaceGeometry->Warning2Count));
2830 0 : ShowContinueError(state, "Note that originally entered dimensions are overridden.");
2831 0 : ShowContinueError(state, "For explicit details on each window, use Output:Diagnostics,DisplayExtraWarnings;");
2832 : }
2833 771 : if (state.dataSurfaceGeometry->Warning3Count > 0) {
2834 0 : ShowWarningMessage(state,
2835 0 : format("{}Interior Windows have been replaced with Window 5/6 two glazing systems, {} times.",
2836 : RoutineName,
2837 0 : state.dataSurfaceGeometry->Warning3Count));
2838 0 : ShowContinueError(state, "Note that originally entered dimensions are overridden.");
2839 0 : ShowContinueError(state, "For explicit details on each window, use Output:Diagnostics,DisplayExtraWarnings;");
2840 : }
2841 :
2842 771 : if (state.dataErrTracking->TotalMultipliedWindows > 0) {
2843 3 : ShowWarningMessage(state,
2844 3 : format("{}There are {} window/glass door(s) that may cause inaccurate shadowing due to Solar Distribution.",
2845 : RoutineName,
2846 2 : state.dataErrTracking->TotalMultipliedWindows));
2847 1 : ShowContinueError(state, "For explicit details on each window, use Output:Diagnostics,DisplayExtraWarnings;");
2848 1 : state.dataErrTracking->TotalWarningErrors += state.dataErrTracking->TotalMultipliedWindows;
2849 : }
2850 771 : if (state.dataErrTracking->TotalCoincidentVertices > 0) {
2851 0 : ShowWarningMessage(state,
2852 0 : format("{}There are {} coincident/collinear vertices; These have been deleted unless the deletion would bring the "
2853 : "number of surface sides < 3.",
2854 : RoutineName,
2855 0 : state.dataErrTracking->TotalCoincidentVertices));
2856 0 : ShowContinueError(state, "For explicit details on each problem surface, use Output:Diagnostics,DisplayExtraWarnings;");
2857 0 : state.dataErrTracking->TotalWarningErrors += state.dataErrTracking->TotalCoincidentVertices;
2858 : }
2859 771 : if (state.dataErrTracking->TotalDegenerateSurfaces > 0) {
2860 0 : ShowSevereMessage(state,
2861 0 : format("{}There are {} degenerate surfaces; Degenerate surfaces are those with number of sides < 3.",
2862 : RoutineName,
2863 0 : state.dataErrTracking->TotalDegenerateSurfaces));
2864 0 : ShowContinueError(state, "These surfaces should be deleted.");
2865 0 : ShowContinueError(state, "For explicit details on each problem surface, use Output:Diagnostics,DisplayExtraWarnings;");
2866 0 : state.dataErrTracking->TotalSevereErrors += state.dataErrTracking->TotalDegenerateSurfaces;
2867 : }
2868 :
2869 771 : GetHTSurfExtVentedCavityData(state, ErrorsFound);
2870 :
2871 771 : state.dataSurfaceGeometry->exposedFoundationPerimeter.getData(state, ErrorsFound);
2872 :
2873 771 : GetSurfaceHeatTransferAlgorithmOverrides(state, ErrorsFound);
2874 :
2875 : // Set up enclosures, process Air Boundaries if any
2876 771 : SetupEnclosuresAndAirBoundaries(state, state.dataViewFactor->EnclRadInfo, SurfaceGeometry::enclosureType::RadiantEnclosures, ErrorsFound);
2877 :
2878 771 : GetSurfaceGroundSurfsData(state, ErrorsFound);
2879 :
2880 771 : GetSurfaceSrdSurfsData(state, ErrorsFound);
2881 :
2882 771 : GetSurfaceLocalEnvData(state, ErrorsFound);
2883 :
2884 771 : if (SurfError || ErrorsFound) {
2885 0 : ErrorsFound = true;
2886 0 : ShowFatalError(state, std::string{RoutineName} + "Errors discovered, program terminates.");
2887 : }
2888 :
2889 1542 : int TotShadSurf = TotDetachedFixed + TotDetachedBldg + TotRectDetachedFixed + TotRectDetachedBldg + TotShdSubs + TotOverhangs +
2890 771 : TotOverhangsProjection + TotFins + TotFinsProjection;
2891 771 : int NumDElightCmplxFen = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Daylighting:DElight:ComplexFenestration");
2892 771 : if (TotShadSurf > 0 && (NumDElightCmplxFen > 0 || DaylightingManager::doesDayLightingUseDElight(state))) {
2893 0 : ShowWarningError(state,
2894 0 : std::string{RoutineName} + "When using DElight daylighting the presence of exterior shading surfaces is ignored.");
2895 : }
2896 :
2897 44533 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; SurfNum++) {
2898 : // Initialize run time surface arrays
2899 43762 : state.dataSurface->SurfActiveConstruction(SurfNum) = state.dataSurface->Surface(SurfNum).Construction;
2900 43762 : state.dataSurface->Surface(SurfNum).RepresentativeCalcSurfNum = SurfNum;
2901 : }
2902 :
2903 : // Representative surface calculations: Assign representative heat transfer surfaces
2904 1543 : if (state.dataSurface->UseRepresentativeSurfaceCalculations &&
2905 772 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "ZoneProperty:UserViewFactors:BySurfaceName") == 0) {
2906 47 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
2907 92 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
2908 46 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
2909 625 : for (int surfNum = thisSpace.HTSurfaceFirst; surfNum <= thisSpace.HTSurfaceLast; surfNum++) {
2910 579 : auto &surface(state.dataSurface->Surface(surfNum));
2911 : // Conditions where surface always needs to be unique
2912 : bool forceUniqueSurface =
2913 1158 : surface.HasShadeControl ||
2914 1158 : state.dataSurface->SurfWinAirflowSource(surfNum) != DataSurfaces::WindowAirFlowSource::Invalid ||
2915 1158 : state.dataConstruction->Construct(surface.Construction).SourceSinkPresent ||
2916 1737 : surface.Class == SurfaceClass::TDD_Dome ||
2917 757 : (surface.Class == SurfaceClass::Window &&
2918 356 : (state.dataSurface->SurfWinOriginalClass(surfNum) == SurfaceClass::TDD_Diffuser ||
2919 356 : state.dataSurface->SurfWinWindowModelType(surfNum) != WindowModel::Detailed ||
2920 356 : state.dataWindowManager->inExtWindowModel->isExternalLibraryModel() ||
2921 757 : state.dataConstruction->Construct(surface.Construction).TCFlag == 1));
2922 579 : if (!forceUniqueSurface) {
2923 579 : state.dataSurface->Surface(surfNum).set_representative_surface(state, surfNum);
2924 : }
2925 : }
2926 : }
2927 : }
2928 : }
2929 : // Initialize surface with movable insulation index list
2930 44533 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; SurfNum++) {
2931 43762 : if (state.dataSurface->SurfMaterialMovInsulExt(SurfNum) > 0 || state.dataSurface->SurfMaterialMovInsulInt(SurfNum) > 0) {
2932 5 : state.dataHeatBalSurf->SurfMovInsulIndexList.push_back(SurfNum);
2933 : }
2934 : }
2935 : }
2936 : }
2937 :
2938 771 : void CreateMissingSpaces(EnergyPlusData &state, Array1D<SurfaceGeometry::SurfaceData> &Surfaces)
2939 : {
2940 : // Scan surfaces to see if Space was assigned in input
2941 44533 : for (int surfNum = 1; surfNum <= state.dataSurface->TotSurfaces; ++surfNum) {
2942 43762 : auto &thisSurf = Surfaces(surfNum);
2943 43762 : if (!thisSurf.HeatTransSurf) continue; // ignore shading surfaces
2944 42220 : if (thisSurf.BaseSurf != surfNum) {
2945 : // Set space for subsurfaces
2946 6442 : thisSurf.spaceNum = Surfaces(thisSurf.BaseSurf).spaceNum;
2947 : }
2948 42220 : if (thisSurf.spaceNum > 0) {
2949 27 : state.dataHeatBal->Zone(thisSurf.Zone).anySurfacesWithSpace = true;
2950 : } else {
2951 42193 : state.dataHeatBal->Zone(thisSurf.Zone).anySurfacesWithoutSpace = true;
2952 : }
2953 : }
2954 :
2955 : // Create any missing Spaces
2956 5585 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
2957 4814 : auto &thisZone = state.dataHeatBal->Zone(zoneNum);
2958 4814 : if (thisZone.anySurfacesWithoutSpace) {
2959 : // If any surfaces in the zone are not assigned to a space, may need to create a new space
2960 : // Every zone has at least one space, created in HeatBalanceManager::GetSpaceData
2961 : // If no surfaces have a space assigned, then the default space will be used, otherwise, create a new space
2962 4812 : if (thisZone.anySurfacesWithSpace) {
2963 : // Add new space
2964 1 : ++state.dataGlobal->numSpaces;
2965 1 : state.dataHeatBal->space(state.dataGlobal->numSpaces).zoneNum = zoneNum;
2966 : // Add to zone's list of spaces
2967 1 : thisZone.spaceIndexes.emplace_back(state.dataGlobal->numSpaces);
2968 1 : ++state.dataHeatBal->Zone(zoneNum).numSpaces;
2969 1 : assert(state.dataHeatBal->Zone(zoneNum).numSpaces == int(state.dataHeatBal->Zone(zoneNum).spaceIndexes.size()));
2970 : // If some surfaces in the zone are assigned to a space, the new space is the remainder of the zone
2971 1 : state.dataHeatBal->space(state.dataGlobal->numSpaces).Name = thisZone.Name + "-Remainder";
2972 1 : state.dataHeatBal->space(state.dataGlobal->numSpaces).isRemainderSpace = true;
2973 1 : state.dataHeatBal->space(state.dataGlobal->numSpaces).spaceType = "GENERAL";
2974 1 : state.dataHeatBal->space(state.dataGlobal->numSpaces).spaceTypeNum = HeatBalanceManager::GetGeneralSpaceTypeNum(state);
2975 : }
2976 : }
2977 : }
2978 :
2979 : // Assign Spaces to surfaces without one
2980 44533 : for (int surfNum = 1; surfNum <= state.dataSurface->TotSurfaces; ++surfNum) {
2981 43762 : auto &thisSurf = Surfaces(surfNum);
2982 43762 : if (!thisSurf.HeatTransSurf) continue; // ignore shading surfaces
2983 42220 : if (thisSurf.spaceNum == 0) {
2984 42193 : int const numSpaces = state.dataHeatBal->Zone(thisSurf.Zone).numSpaces;
2985 42193 : int const lastSpaceForZone = state.dataHeatBal->Zone(thisSurf.Zone).spaceIndexes(numSpaces);
2986 42193 : thisSurf.spaceNum = lastSpaceForZone;
2987 : }
2988 : }
2989 771 : }
2990 :
2991 771 : void createSpaceSurfaceLists(EnergyPlusData &state, bool &ErrorsFound)
2992 : {
2993 : static constexpr std::string_view RoutineName("createSpaceSurfaceLists: ");
2994 : // Build Space surface lists now that all of the surface sorting is complete
2995 44533 : for (int surfNum = 1; surfNum <= state.dataSurface->TotSurfaces; ++surfNum) {
2996 43762 : auto &thisSurf = state.dataSurface->Surface(surfNum);
2997 43762 : if (!thisSurf.HeatTransSurf) continue; // ignore shading surfaces
2998 : // Add to Space's list of surfaces
2999 42220 : state.dataHeatBal->space(thisSurf.spaceNum).surfaces.emplace_back(surfNum);
3000 : }
3001 : // TODO MJW: Is this necessary? Check that all Spaces have at least one Surface
3002 4848 : for (int spaceNum = 1; spaceNum < state.dataGlobal->numSpaces; ++spaceNum) {
3003 4077 : if (int(state.dataHeatBal->space(spaceNum).surfaces.size()) == 0) {
3004 0 : ShowSevereError(state, std::string(RoutineName) + "Space = " + state.dataHeatBal->space(spaceNum).Name + " has no surfaces.");
3005 0 : ErrorsFound = true;
3006 : }
3007 : }
3008 771 : }
3009 6442 : void checkSubSurfAzTiltNorm(EnergyPlusData &state,
3010 : SurfaceData &baseSurface, // Base surface data (in)
3011 : SurfaceData &subSurface, // Subsurface data (in)
3012 : bool &surfaceError // True if surface azimuths or tilts differ by more than error tolerance
3013 : )
3014 : {
3015 6442 : bool sameSurfNormal(false); // True if surface has the same surface normal within tolerance
3016 6442 : bool baseSurfHoriz(false); // True if base surface is near horizontal
3017 6442 : Real64 constexpr warningTolerance(30.0);
3018 6442 : Real64 constexpr errorTolerance(90.0);
3019 :
3020 6442 : surfaceError = false;
3021 :
3022 : // Check if base surface and subsurface have the same normal
3023 6442 : Vectors::CompareTwoVectors(baseSurface.NewellSurfaceNormalVector, subSurface.NewellSurfaceNormalVector, sameSurfNormal, 0.001);
3024 6442 : if (sameSurfNormal) { // copy lcs vectors
3025 : // Prior logic tested for azimuth difference < 30 and then skipped this - this caused large diffs in
3026 : // CmplxGlz_MeasuredDeflectionAndShading Restoring that check here but will require further investigation (MJW Dec 2015)
3027 6441 : if (std::abs(baseSurface.Azimuth - subSurface.Azimuth) > warningTolerance) {
3028 60 : subSurface.lcsx = baseSurface.lcsx;
3029 60 : subSurface.lcsy = baseSurface.lcsy;
3030 60 : subSurface.lcsy = baseSurface.lcsy;
3031 : }
3032 : } else {
3033 : // Not sure what this does, but keeping for now (MJW Dec 2015)
3034 1 : if (std::abs(subSurface.Azimuth - 360.0) < 0.01) {
3035 0 : subSurface.Azimuth = 360.0 - subSurface.Azimuth;
3036 : }
3037 1 : if (std::abs(baseSurface.Azimuth - 360.0) < 0.01) {
3038 0 : baseSurface.Azimuth = 360.0 - baseSurface.Azimuth;
3039 : }
3040 :
3041 : // Is base surface horizontal? If so, ignore azimuth differences
3042 1 : if (std::abs(baseSurface.Tilt) <= 1.0e-5 || std::abs(baseSurface.Tilt - 180.0) <= 1.0e-5) baseSurfHoriz = true;
3043 :
3044 2 : if (((std::abs(baseSurface.Azimuth - subSurface.Azimuth) > errorTolerance) && !baseSurfHoriz) ||
3045 1 : (std::abs(baseSurface.Tilt - subSurface.Tilt) > errorTolerance)) {
3046 0 : surfaceError = true;
3047 0 : ShowSevereError(
3048 : state,
3049 0 : format("checkSubSurfAzTiltNorm: Outward facing angle of subsurface differs more than {:.1R} degrees from base surface.",
3050 0 : errorTolerance));
3051 0 : ShowContinueError(state,
3052 0 : format("Subsurface=\"{}\" Tilt = {:.1R} Azimuth = {:.1R}", subSurface.Name, subSurface.Tilt, subSurface.Azimuth));
3053 0 : ShowContinueError(
3054 0 : state, format("Base surface=\"{}\" Tilt = {:.1R} Azimuth = {:.1R}", baseSurface.Name, baseSurface.Tilt, baseSurface.Azimuth));
3055 2 : } else if (((std::abs(baseSurface.Azimuth - subSurface.Azimuth) > warningTolerance) && !baseSurfHoriz) ||
3056 1 : (std::abs(baseSurface.Tilt - subSurface.Tilt) > warningTolerance)) {
3057 0 : ++state.dataSurfaceGeometry->checkSubSurfAzTiltNormErrCount;
3058 0 : if (state.dataSurfaceGeometry->checkSubSurfAzTiltNormErrCount == 1 && !state.dataGlobal->DisplayExtraWarnings) {
3059 0 : ShowWarningError(state,
3060 0 : format("checkSubSurfAzTiltNorm: Some Outward Facing angles of subsurfaces differ more than {:.1R} "
3061 : "degrees from base surface.",
3062 0 : warningTolerance));
3063 0 : ShowContinueError(state, "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on individual surfaces.");
3064 : }
3065 0 : if (state.dataGlobal->DisplayExtraWarnings) {
3066 0 : ShowWarningError(
3067 : state,
3068 0 : format("checkSubSurfAzTiltNorm: Outward facing angle of subsurface differs more than {:.1R} degrees from base surface.",
3069 0 : warningTolerance));
3070 0 : ShowContinueError(
3071 0 : state, format("Subsurface=\"{}\" Tilt = {:.1R} Azimuth = {:.1R}", subSurface.Name, subSurface.Tilt, subSurface.Azimuth));
3072 0 : ShowContinueError(
3073 : state,
3074 0 : format("Base surface=\"{}\" Tilt = {:.1R} Azimuth = {:.1R}", baseSurface.Name, baseSurface.Tilt, baseSurface.Azimuth));
3075 : }
3076 : }
3077 : }
3078 6442 : }
3079 :
3080 771 : void GetGeometryParameters(EnergyPlusData &state, bool &ErrorsFound) // set to true if errors found during input
3081 : {
3082 :
3083 : // SUBROUTINE INFORMATION:
3084 : // AUTHOR Linda Lawrie
3085 : // DATE WRITTEN May 2000
3086 : // MODIFIED na
3087 : // RE-ENGINEERED na
3088 :
3089 : // PURPOSE OF THIS SUBROUTINE:
3090 : // This subroutine reads in the "Surface Geometry" parameters, verifies them,
3091 : // and sets "global" variables that will tell other routines how the surface
3092 : // vertices are expected in input.
3093 :
3094 : // METHODOLOGY EMPLOYED:
3095 : // na
3096 :
3097 : // REFERENCES:
3098 : // GlobalGeometryRules Definition
3099 : // GlobalGeometryRules,
3100 : // \required-object
3101 : // \unique-object
3102 : // A1, \field Starting Vertex Position
3103 : // \required-field
3104 : // \note Specified as entry for a 4 sided surface/rectangle
3105 : // \note Surfaces are specified as viewed from outside the surface
3106 : // \note Shading surfaces as viewed from behind. (towards what they are shading)
3107 : // \type choice
3108 : // \key UpperLeftCorner
3109 : // \key LowerLeftCorner
3110 : // \key UpperRightCorner
3111 : // \key LowerRightCorner
3112 : // A2, \field Vertex Entry Direction
3113 : // \required-field
3114 : // \type choice
3115 : // \key Counterclockwise
3116 : // \key Clockwise
3117 : // A3, \field Coordinate System
3118 : // \required-field
3119 : // \note relative -- coordinates are entered relative to zone origin
3120 : // \note world -- all coordinates entered are "absolute" for this facility
3121 : // \note absolute -- same as world
3122 : // \type choice
3123 : // \key Relative
3124 : // \key World
3125 : // \key Absolute
3126 : // A4, \field Daylighting Reference Point Coordinate System
3127 : // \type choice
3128 : // \key Relative
3129 : // \default Relative
3130 : // \note Relative -- coordinates are entered relative to zone origin
3131 : // \key World
3132 : // \note World -- all coordinates entered are "absolute" for this facility
3133 : // \key Absolute
3134 : // \note absolute -- same as world
3135 : // A5; \field Rectangular Surface Coordinate System
3136 : // \type choice
3137 : // \key Relative
3138 : // \default Relative
3139 : // \note Relative -- Starting corner is entered relative to zone origin
3140 : // \key World
3141 : // \note World -- Starting corner is entered in "absolute"
3142 : // \key Absolute
3143 : // \note absolute -- same as world
3144 :
3145 : // Using/Aliasing
3146 :
3147 : // SUBROUTINE PARAMETER DEFINITIONS:
3148 771 : static Array1D_string const FlCorners(4, {"UpperLeftCorner", "LowerLeftCorner", "LowerRightCorner", "UpperRightCorner"});
3149 :
3150 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3151 : int NumStmt;
3152 1542 : Array1D_string GAlphas(5);
3153 : int NAlphas;
3154 1542 : Array1D<Real64> GNum(1);
3155 : int NNum;
3156 : int IOStat;
3157 : bool OK;
3158 : int Found;
3159 1542 : std::string OutMsg;
3160 : int ZoneNum; // For loop counter
3161 771 : bool RelWarning(false);
3162 771 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
3163 :
3164 771 : cCurrentModuleObject = "GlobalGeometryRules";
3165 771 : NumStmt = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
3166 771 : OutMsg = " Surface Geometry,";
3167 :
3168 : {
3169 771 : auto const SELECT_CASE_var(NumStmt);
3170 :
3171 771 : if (SELECT_CASE_var == 1) {
3172 : // This is the valid case
3173 3855 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
3174 : cCurrentModuleObject,
3175 : 1,
3176 : GAlphas,
3177 : NAlphas,
3178 : GNum,
3179 : NNum,
3180 : IOStat,
3181 771 : state.dataIPShortCut->lNumericFieldBlanks,
3182 771 : state.dataIPShortCut->lAlphaFieldBlanks,
3183 771 : state.dataIPShortCut->cAlphaFieldNames,
3184 771 : state.dataIPShortCut->cNumericFieldNames);
3185 :
3186 : // Even though these will be validated, set defaults in case error here -- wont
3187 : // cause aborts in later surface gets (hopefully)
3188 771 : state.dataSurface->Corner = UpperLeftCorner;
3189 771 : state.dataSurface->WorldCoordSystem = true;
3190 771 : state.dataSurface->CCW = true;
3191 :
3192 771 : OK = false;
3193 771 : Found = UtilityRoutines::FindItem(GAlphas(1), FlCorners, 4);
3194 771 : if (Found == 0) {
3195 0 : ShowSevereError(state, cCurrentModuleObject + ": Invalid " + state.dataIPShortCut->cAlphaFieldNames(1) + '=' + GAlphas(1));
3196 0 : ErrorsFound = true;
3197 : } else {
3198 771 : state.dataSurface->Corner = Found;
3199 771 : OK = true;
3200 771 : OutMsg += FlCorners(state.dataSurface->Corner) + ',';
3201 : }
3202 :
3203 771 : OK = false;
3204 771 : if (UtilityRoutines::SameString(GAlphas(2), "CCW") || UtilityRoutines::SameString(GAlphas(2), "Counterclockwise")) {
3205 768 : state.dataSurface->CCW = true;
3206 768 : OutMsg += "Counterclockwise,";
3207 768 : OK = true;
3208 : }
3209 771 : if (UtilityRoutines::SameString(GAlphas(2), "CW") || UtilityRoutines::SameString(GAlphas(2), "Clockwise")) {
3210 3 : state.dataSurface->CCW = false;
3211 3 : OutMsg += "Clockwise,";
3212 3 : OK = true;
3213 : }
3214 771 : if (!OK) {
3215 0 : ShowSevereError(state, cCurrentModuleObject + ": Invalid " + state.dataIPShortCut->cAlphaFieldNames(2) + '=' + GAlphas(2));
3216 0 : ErrorsFound = true;
3217 : }
3218 :
3219 771 : OK = false;
3220 771 : if (UtilityRoutines::SameString(GAlphas(3), "World") || UtilityRoutines::SameString(GAlphas(3), "Absolute")) {
3221 351 : state.dataSurface->WorldCoordSystem = true;
3222 351 : OutMsg += "WorldCoordinateSystem,";
3223 351 : OK = true;
3224 : }
3225 771 : if (UtilityRoutines::SameString(GAlphas(3), "Relative")) {
3226 420 : state.dataSurface->WorldCoordSystem = false;
3227 420 : OutMsg += "RelativeCoordinateSystem,";
3228 420 : OK = true;
3229 : }
3230 771 : if (!OK) {
3231 0 : ShowWarningError(state, cCurrentModuleObject + ": Invalid " + state.dataIPShortCut->cAlphaFieldNames(3) + '=' + GAlphas(3));
3232 0 : ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(3) + " defaults to \"WorldCoordinateSystem\"");
3233 0 : state.dataSurface->WorldCoordSystem = true;
3234 0 : OutMsg += "WorldCoordinateSystem,";
3235 : }
3236 :
3237 771 : OK = false;
3238 771 : if (UtilityRoutines::SameString(GAlphas(4), "World") || UtilityRoutines::SameString(GAlphas(4), "Absolute")) {
3239 8 : state.dataSurface->DaylRefWorldCoordSystem = true;
3240 8 : OutMsg += "WorldCoordinateSystem,";
3241 8 : OK = true;
3242 : }
3243 771 : if (UtilityRoutines::SameString(GAlphas(4), "Relative") || GAlphas(4).empty()) {
3244 763 : state.dataSurface->DaylRefWorldCoordSystem = false;
3245 763 : OutMsg += "RelativeCoordinateSystem,";
3246 763 : OK = true;
3247 : }
3248 771 : if (!OK) {
3249 0 : ShowWarningError(state, cCurrentModuleObject + ": Invalid " + state.dataIPShortCut->cAlphaFieldNames(4) + '=' + GAlphas(4));
3250 0 : ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(4) + " defaults to \"RelativeToZoneOrigin\"");
3251 0 : state.dataSurface->DaylRefWorldCoordSystem = false;
3252 0 : OutMsg += "RelativeToZoneOrigin,";
3253 : }
3254 :
3255 771 : OK = false;
3256 771 : if (UtilityRoutines::SameString(GAlphas(5), "World") || UtilityRoutines::SameString(GAlphas(5), "Absolute")) {
3257 17 : state.dataSurfaceGeometry->RectSurfRefWorldCoordSystem = true;
3258 17 : OutMsg += "WorldCoordinateSystem";
3259 17 : OK = true;
3260 : }
3261 771 : if (UtilityRoutines::SameString(GAlphas(5), "Relative") || GAlphas(5).empty()) {
3262 754 : state.dataSurfaceGeometry->RectSurfRefWorldCoordSystem = false;
3263 754 : OutMsg += "RelativeToZoneOrigin";
3264 754 : OK = true;
3265 : }
3266 771 : if (!OK) {
3267 0 : ShowWarningError(state, cCurrentModuleObject + ": Invalid " + state.dataIPShortCut->cAlphaFieldNames(5) + '=' + GAlphas(5));
3268 0 : ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(5) + " defaults to \"RelativeToZoneOrigin\"");
3269 0 : state.dataSurfaceGeometry->RectSurfRefWorldCoordSystem = false;
3270 0 : OutMsg += "RelativeToZoneOrigin";
3271 : }
3272 :
3273 0 : } else if (SELECT_CASE_var == 0) {
3274 :
3275 0 : ShowSevereError(state, cCurrentModuleObject + ": Required object not found.");
3276 0 : OutMsg += "None found in input";
3277 0 : ErrorsFound = true;
3278 :
3279 : } else {
3280 :
3281 0 : ShowSevereError(state, cCurrentModuleObject + ": Too many objects entered. Only one allowed.");
3282 0 : ErrorsFound = true;
3283 : }
3284 : }
3285 :
3286 771 : if (!state.dataSurface->WorldCoordSystem) {
3287 420 : if (state.dataSurface->DaylRefWorldCoordSystem) {
3288 0 : ShowWarningError(state, cCurrentModuleObject + ": Potential mismatch of coordinate specifications.");
3289 0 : ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + GAlphas(3) + "\"; while ");
3290 0 : ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + GAlphas(4) + "\".");
3291 : }
3292 420 : if (state.dataSurfaceGeometry->RectSurfRefWorldCoordSystem) {
3293 0 : ShowWarningError(state, cCurrentModuleObject + ": Potential mismatch of coordinate specifications.");
3294 0 : ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + GAlphas(3) + "\"; while ");
3295 0 : ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(5) + "=\"" + GAlphas(5) + "\".");
3296 : }
3297 : } else {
3298 351 : RelWarning = false;
3299 1372 : for (ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
3300 1021 : if (state.dataHeatBal->Zone(ZoneNum).OriginX != 0.0) RelWarning = true;
3301 1021 : if (state.dataHeatBal->Zone(ZoneNum).OriginY != 0.0) RelWarning = true;
3302 1021 : if (state.dataHeatBal->Zone(ZoneNum).OriginZ != 0.0) RelWarning = true;
3303 : }
3304 351 : if (RelWarning && !state.dataSurfaceGeometry->RectSurfRefWorldCoordSystem) {
3305 0 : ShowWarningError(state,
3306 0 : cCurrentModuleObject + ": Potential mismatch of coordinate specifications. Note that the rectangular surfaces are "
3307 : "relying on the default SurfaceGeometry for 'Relative to zone' coordinate.");
3308 0 : ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + GAlphas(3) + "\"; while ");
3309 0 : if (GAlphas(5) == "RELATIVE") {
3310 0 : ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(5) + "=\"" + GAlphas(5) + "\".");
3311 0 : } else if (GAlphas(5) != "ABSOLUTE") {
3312 0 : ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(5) + "=\"defaults to RELATIVE\".");
3313 : }
3314 : }
3315 : }
3316 :
3317 771 : print(state.files.eio,
3318 : "! <Surface Geometry>,Starting Corner,Vertex Input Direction,Coordinate System,Daylight Reference "
3319 771 : "Point Coordinate System,Rectangular (Simple) Surface Coordinate System\n");
3320 771 : print(state.files.eio, "{}\n", OutMsg);
3321 771 : }
3322 :
3323 771 : void GetDetShdSurfaceData(EnergyPlusData &state,
3324 : bool &ErrorsFound, // Error flag indicator (true if errors found)
3325 : int &SurfNum, // Count of Current SurfaceNumber
3326 : int const TotDetachedFixed, // Number of Fixed Detached Shading Surfaces to obtain
3327 : int const TotDetachedBldg // Number of Building Detached Shading Surfaces to obtain
3328 : )
3329 : {
3330 : // SUBROUTINE INFORMATION:
3331 : // AUTHOR Linda Lawrie
3332 : // DATE WRITTEN May 2000
3333 :
3334 : // PURPOSE OF THIS SUBROUTINE:
3335 : // This subroutine gets the Detached Shading Surface Data,
3336 : // checks it for errors, etc.
3337 :
3338 : // Using/Aliasing
3339 : using ScheduleManager::CheckScheduleValueMinMax;
3340 : using ScheduleManager::GetScheduleIndex;
3341 : using ScheduleManager::GetScheduleMaxValue;
3342 : using ScheduleManager::GetScheduleMinValue;
3343 :
3344 : // SUBROUTINE PARAMETER DEFINITIONS:
3345 771 : static Array1D_string const cModuleObjects(2, {"Shading:Site:Detailed", "Shading:Building:Detailed"});
3346 :
3347 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3348 : int IOStat; // IO Status when calling get input subroutine
3349 : int NumAlphas; // Number of material alpha names being passed
3350 : int NumNumbers; // Number of material properties being passed
3351 : int Loop;
3352 : int Item;
3353 : int ItemsToGet;
3354 : SurfaceClass ClassItem;
3355 : int numSides;
3356 : Real64 SchedMinValue;
3357 : Real64 SchedMaxValue;
3358 :
3359 771 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
3360 :
3361 771 : if ((TotDetachedFixed + TotDetachedBldg) > 0 && state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::Minimal) {
3362 0 : ShowWarningError(state, "Detached shading effects are ignored when Solar Distribution = MinimalShadowing");
3363 : }
3364 :
3365 771 : if ((TotDetachedFixed + TotDetachedBldg) == 0) return;
3366 :
3367 54 : for (Item = 1; Item <= 2; ++Item) {
3368 :
3369 36 : cCurrentModuleObject = cModuleObjects(Item);
3370 36 : if (Item == 1) {
3371 18 : ItemsToGet = TotDetachedFixed;
3372 18 : ClassItem = SurfaceClass::Detached_F;
3373 : } else { // IF (Item == 2) THEN
3374 18 : ItemsToGet = TotDetachedBldg;
3375 18 : ClassItem = SurfaceClass::Detached_B;
3376 : }
3377 :
3378 36 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, Loop, NumAlphas, NumNumbers);
3379 36 : if (NumAlphas != 2) {
3380 0 : ShowSevereError(
3381 0 : state, format("{}: Object Definition indicates not = 2 Alpha Objects, Number Indicated={}", cCurrentModuleObject, NumAlphas));
3382 0 : ErrorsFound = true;
3383 : }
3384 :
3385 86 : for (Loop = 1; Loop <= ItemsToGet; ++Loop) {
3386 350 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
3387 : cCurrentModuleObject,
3388 : Loop,
3389 50 : state.dataIPShortCut->cAlphaArgs,
3390 : NumAlphas,
3391 50 : state.dataIPShortCut->rNumericArgs,
3392 : NumNumbers,
3393 : IOStat,
3394 50 : state.dataIPShortCut->lNumericFieldBlanks,
3395 50 : state.dataIPShortCut->lAlphaFieldBlanks,
3396 50 : state.dataIPShortCut->cAlphaFieldNames,
3397 50 : state.dataIPShortCut->cNumericFieldNames);
3398 :
3399 100 : if (GlobalNames::VerifyUniqueInterObjectName(state,
3400 50 : state.dataSurfaceGeometry->UniqueSurfaceNames,
3401 50 : state.dataIPShortCut->cAlphaArgs(1),
3402 : cCurrentModuleObject,
3403 50 : state.dataIPShortCut->cAlphaFieldNames(1),
3404 : ErrorsFound)) {
3405 0 : continue;
3406 : }
3407 :
3408 50 : ++SurfNum;
3409 50 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name = state.dataIPShortCut->cAlphaArgs(1); // Set the Surface Name in the Derived Type
3410 50 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = ClassItem;
3411 50 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf = false;
3412 : // Base transmittance of a shadowing (sub)surface
3413 50 : if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) {
3414 : // Schedule for a shadowing (sub)surface
3415 26 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex =
3416 26 : GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(2));
3417 26 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex == 0) {
3418 0 : ShowSevereError(state,
3419 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", " +
3420 0 : state.dataIPShortCut->cAlphaFieldNames(2) + " not found=" + state.dataIPShortCut->cAlphaArgs(2));
3421 0 : ErrorsFound = true;
3422 : }
3423 : } else {
3424 24 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex = 0;
3425 : }
3426 50 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex != 0) {
3427 26 : if (!CheckScheduleValueMinMax(state, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex, ">=", 0.0, "<=", 1.0)) {
3428 0 : ShowSevereError(state,
3429 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", " +
3430 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) +
3431 : "\", values not in range [0,1].");
3432 0 : ErrorsFound = true;
3433 : }
3434 26 : SchedMinValue = GetScheduleMinValue(state, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex);
3435 26 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedMinValue = SchedMinValue;
3436 26 : SchedMaxValue = GetScheduleMaxValue(state, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex);
3437 26 : if (SchedMinValue == 1.0) {
3438 0 : ShowWarningError(state,
3439 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", " +
3440 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) +
3441 : "\", is always transparent.");
3442 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).IsTransparent = true;
3443 : }
3444 26 : if (SchedMinValue < 0.0) {
3445 0 : ShowSevereError(state,
3446 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", " +
3447 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) +
3448 : "\", has schedule values < 0.");
3449 0 : ShowContinueError(state, "...Schedule values < 0 have no meaning for shading elements.");
3450 : }
3451 26 : if (SchedMaxValue > 0.0) {
3452 26 : state.dataSolarShading->anyScheduledShadingSurface = true;
3453 : }
3454 26 : if (SchedMaxValue > 1.0) {
3455 0 : ShowSevereError(state,
3456 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", " +
3457 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) +
3458 : "\", has schedule values > 1.");
3459 0 : ShowContinueError(state, "...Schedule values > 1 have no meaning for shading elements.");
3460 : }
3461 26 : if (std::abs(SchedMinValue - SchedMaxValue) > 1.0e-6) {
3462 0 : state.dataSurface->ShadingTransmittanceVaries = true;
3463 : }
3464 : }
3465 50 : if (state.dataIPShortCut->lNumericFieldBlanks(1) || state.dataIPShortCut->rNumericArgs(1) == DataGlobalConstants::AutoCalculate) {
3466 0 : numSides = (NumNumbers - 1) / 3;
3467 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = numSides;
3468 0 : if (mod(NumNumbers - 1, 3) != 0) {
3469 0 : ShowWarningError(state,
3470 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", " +
3471 0 : format("{} not even multiple of 3. Will read in {}",
3472 0 : state.dataIPShortCut->cNumericFieldNames(1),
3473 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides));
3474 : }
3475 0 : if (numSides < 3) {
3476 0 : ShowSevereError(state,
3477 0 : format("{}=\"{}\", {} (autocalculate) must be >= 3. Only {} provided.",
3478 : cCurrentModuleObject,
3479 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
3480 0 : state.dataIPShortCut->cNumericFieldNames(1),
3481 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides));
3482 0 : ErrorsFound = true;
3483 0 : continue;
3484 : }
3485 : } else {
3486 50 : numSides = (NumNumbers - 1) / 3;
3487 50 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = state.dataIPShortCut->rNumericArgs(1);
3488 50 : if (numSides > state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides) {
3489 0 : ShowWarningError(state,
3490 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", field " +
3491 0 : state.dataIPShortCut->cNumericFieldNames(1) + '=' +
3492 0 : fmt::to_string(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides));
3493 0 : ShowContinueError(state,
3494 0 : format("...but {} were entered. Only the indicated {} will be used.",
3495 : numSides,
3496 0 : state.dataIPShortCut->cNumericFieldNames(1)));
3497 : }
3498 : }
3499 50 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.allocate(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
3500 50 : GetVertices(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides, state.dataIPShortCut->rNumericArgs({2, _}));
3501 50 : CheckConvexity(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
3502 50 : if (state.dataReportFlag->MakeMirroredDetachedShading) {
3503 50 : MakeMirrorSurface(state, SurfNum);
3504 : }
3505 : }
3506 :
3507 : } // Item Loop
3508 : }
3509 :
3510 771 : void GetRectDetShdSurfaceData(EnergyPlusData &state,
3511 : bool &ErrorsFound, // Error flag indicator (true if errors found)
3512 : int &SurfNum, // Count of Current SurfaceNumber
3513 : int const TotRectDetachedFixed, // Number of Fixed Detached Shading Surfaces to obtain
3514 : int const TotRectDetachedBldg // Number of Building Detached Shading Surfaces to obtain
3515 : )
3516 : {
3517 :
3518 : // SUBROUTINE INFORMATION:
3519 : // AUTHOR Linda Lawrie
3520 : // DATE WRITTEN January 2009
3521 : // MODIFIED na
3522 : // RE-ENGINEERED na
3523 :
3524 : // PURPOSE OF THIS SUBROUTINE:
3525 : // Gets the simple, rectangular detached surfaces.
3526 :
3527 : // Using/Aliasing
3528 :
3529 : // SUBROUTINE PARAMETER DEFINITIONS:
3530 771 : static Array1D_string const cModuleObjects(2, {"Shading:Site", "Shading:Building"});
3531 :
3532 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3533 : int IOStat; // IO Status when calling get input subroutine
3534 : int NumAlphas; // Number of material alpha names being passed
3535 : int NumNumbers; // Number of material properties being passed
3536 : int Loop;
3537 : int Item;
3538 : int ItemsToGet;
3539 : SurfaceClass ClassItem;
3540 :
3541 771 : if ((TotRectDetachedFixed + TotRectDetachedBldg) > 0 && state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::Minimal) {
3542 0 : ShowWarningError(state, "Detached shading effects are ignored when Solar Distribution = MinimalShadowing");
3543 : }
3544 :
3545 771 : if (TotRectDetachedFixed + TotRectDetachedBldg == 0) return;
3546 6 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
3547 18 : for (Item = 1; Item <= 2; ++Item) {
3548 :
3549 12 : cCurrentModuleObject = cModuleObjects(Item);
3550 12 : if (Item == 1) {
3551 6 : ItemsToGet = TotRectDetachedFixed;
3552 6 : ClassItem = SurfaceClass::Detached_F;
3553 : } else { // IF (Item == 2) THEN
3554 6 : ItemsToGet = TotRectDetachedBldg;
3555 6 : ClassItem = SurfaceClass::Detached_B;
3556 : }
3557 :
3558 12 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, Loop, NumAlphas, NumNumbers);
3559 12 : if (NumAlphas != 1) {
3560 0 : ShowSevereError(
3561 0 : state, format("{}: Object Definition indicates not = 1 Alpha Objects, Number Indicated={}", cCurrentModuleObject, NumAlphas));
3562 0 : ErrorsFound = true;
3563 : }
3564 :
3565 32 : for (Loop = 1; Loop <= ItemsToGet; ++Loop) {
3566 140 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
3567 : cCurrentModuleObject,
3568 : Loop,
3569 20 : state.dataIPShortCut->cAlphaArgs,
3570 : NumAlphas,
3571 20 : state.dataIPShortCut->rNumericArgs,
3572 : NumNumbers,
3573 : IOStat,
3574 20 : state.dataIPShortCut->lNumericFieldBlanks,
3575 20 : state.dataIPShortCut->lAlphaFieldBlanks,
3576 20 : state.dataIPShortCut->cAlphaFieldNames,
3577 20 : state.dataIPShortCut->cNumericFieldNames);
3578 :
3579 40 : if (GlobalNames::VerifyUniqueInterObjectName(state,
3580 20 : state.dataSurfaceGeometry->UniqueSurfaceNames,
3581 20 : state.dataIPShortCut->cAlphaArgs(1),
3582 : cCurrentModuleObject,
3583 20 : state.dataIPShortCut->cAlphaFieldNames(1),
3584 : ErrorsFound)) {
3585 0 : continue;
3586 : }
3587 :
3588 20 : ++SurfNum;
3589 20 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name = state.dataIPShortCut->cAlphaArgs(1); // Set the Surface Name in the Derived Type
3590 20 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = ClassItem;
3591 20 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf = false;
3592 :
3593 20 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth = state.dataIPShortCut->rNumericArgs(1);
3594 20 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Detached_B && !state.dataSurface->WorldCoordSystem) {
3595 4 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth += state.dataHeatBal->BuildingAzimuth;
3596 : }
3597 20 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Detached_B) {
3598 6 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth += state.dataHeatBal->BuildingRotationAppendixG;
3599 : }
3600 20 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt = state.dataIPShortCut->rNumericArgs(2);
3601 20 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConvOrientation =
3602 20 : ConvectionCoefficients::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
3603 :
3604 20 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = 4;
3605 20 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.allocate(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
3606 :
3607 120 : MakeRectangularVertices(state,
3608 : SurfNum,
3609 20 : state.dataIPShortCut->rNumericArgs(3),
3610 20 : state.dataIPShortCut->rNumericArgs(4),
3611 20 : state.dataIPShortCut->rNumericArgs(5),
3612 20 : state.dataIPShortCut->rNumericArgs(6),
3613 20 : state.dataIPShortCut->rNumericArgs(7),
3614 20 : state.dataSurfaceGeometry->RectSurfRefWorldCoordSystem);
3615 :
3616 20 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area <= 0.0) {
3617 0 : ShowSevereError(state,
3618 0 : format("{}=\"{}\", Surface Area <= 0.0; Entered Area={:.2T}",
3619 : cCurrentModuleObject,
3620 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
3621 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area));
3622 0 : ErrorsFound = true;
3623 : }
3624 :
3625 20 : if (state.dataReportFlag->MakeMirroredDetachedShading) {
3626 20 : MakeMirrorSurface(state, SurfNum);
3627 : }
3628 : }
3629 :
3630 : } // Item Loop
3631 : }
3632 :
3633 771 : void GetHTSurfaceData(EnergyPlusData &state,
3634 : bool &ErrorsFound, // Error flag indicator (true if errors found)
3635 : int &SurfNum, // Count of Current SurfaceNumber
3636 : int const TotHTSurfs, // Number of Heat Transfer Base Surfaces to obtain
3637 : int const TotDetailedWalls, // Number of Wall:Detailed items to obtain
3638 : int const TotDetailedRoofs, // Number of RoofCeiling:Detailed items to obtain
3639 : int const TotDetailedFloors, // Number of Floor:Detailed items to obtain
3640 : const Array1D_string &BaseSurfCls, // Valid Classes for Base Surfaces
3641 : const Array1D<SurfaceClass> &BaseSurfIDs,
3642 : int &NeedToAddSurfaces // Number of surfaces to add, based on unentered IZ surfaces
3643 : )
3644 : {
3645 :
3646 : // SUBROUTINE INFORMATION:
3647 : // AUTHOR Linda Lawrie
3648 : // DATE WRITTEN May 2000
3649 : // MODIFIED na
3650 : // RE-ENGINEERED na
3651 :
3652 : // PURPOSE OF THIS SUBROUTINE:
3653 : // This subroutine gets the HeatTransfer Surface Data,
3654 : // checks it for errors, etc.
3655 :
3656 : // METHODOLOGY EMPLOYED:
3657 : // na
3658 :
3659 : // REFERENCES:
3660 : // Heat Transfer Surface Definition
3661 : // BuildingSurface:Detailed,
3662 : // \extensible:3 -- duplicate last set of x,y,z coordinates (last 3 fields), remembering to remove ; from "inner" fields.
3663 : // \format vertices
3664 : // A1 , \field Name
3665 : // \required-field
3666 : // \type alpha
3667 : // \reference SurfaceNames
3668 : // \reference SurfAndSubSurfNames
3669 : // \reference AllHeatTranSurfNames
3670 : // \reference HeatTranBaseSurfNames
3671 : // \reference OutFaceEnvNames
3672 : // \reference AllHeatTranAngFacNames
3673 : // \reference RadGroupAndSurfNames
3674 : // \reference SurfGroupAndHTSurfNames
3675 : // \reference AllShadingAndHTSurfNames
3676 : // A2 , \field Surface Type
3677 : // \required-field
3678 : // \type choice
3679 : // \key Floor
3680 : // \key Wall
3681 : // \key Ceiling
3682 : // \key Roof
3683 : // A3 , \field Construction Name
3684 : // \required-field
3685 : // \note To be matched with a construction in this input file
3686 : // \type object-list
3687 : // \object-list ConstructionNames
3688 : // A4 , \field Zone Name
3689 : // \required-field
3690 : // \note Zone the surface is a part of
3691 : // \type object-list
3692 : // \object-list ZoneNames
3693 : // A5 , \field Outside Boundary Condition
3694 : // \required-field
3695 : // \type choice
3696 : // \key Adiabatic
3697 : // \key Surface
3698 : // \key Zone
3699 : // \key Outdoors
3700 : // \key Ground
3701 : // \key GroundFCfactorMethod
3702 : // \key OtherSideCoefficients
3703 : // \key OtherSideConditionsModel
3704 : // \key GroundSlabPreprocessorAverage
3705 : // \key GroundSlabPreprocessorCore
3706 : // \key GroundSlabPreprocessorPerimeter
3707 : // \key GroundBasementPreprocessorAverageWall
3708 : // \key GroundBasementPreprocessorAverageFloor
3709 : // \key GroundBasementPreprocessorUpperWall
3710 : // \key GroundBasementPreprocessorLowerWall
3711 : // A6, \field Outside Boundary Condition Object
3712 : // \type object-list
3713 : // \object-list OutFaceEnvNames
3714 : // \note Non-blank only if the field Outside Boundary Condition is Surface,
3715 : // \note Zone, OtherSideCoefficients or OtherSideConditionsModel
3716 : // \note If Surface, specify name of corresponding surface in adjacent zone or
3717 : // \note specify current surface name for internal partition separating like zones
3718 : // \note If Zone, specify the name of the corresponding zone and
3719 : // \note the program will generate the corresponding interzone surface
3720 : // \note If OtherSideCoefficients, specify name of SurfaceProperty:OtherSideCoefficients
3721 : // \note If OtherSideConditionsModel, specify name of SurfaceProperty:OtherSideConditionsModel
3722 : // A7 , \field Sun Exposure
3723 : // \required-field
3724 : // \type choice
3725 : // \key SunExposed
3726 : // \key NoSun
3727 : // \default SunExposed
3728 : // A8, \field Wind Exposure
3729 : // \required-field
3730 : // \type choice
3731 : // \key WindExposed
3732 : // \key NoWind
3733 : // \default WindExposed
3734 : // N1, \field View Factor to Ground
3735 : // \type real
3736 : // \note From the exterior of the surface
3737 : // \note Unused if one uses the "reflections" options in Solar Distribution in Building input
3738 : // \note unless a DaylightingDevice:Shelf or DaylightingDevice:Tubular object has been specified.
3739 : // \note autocalculate will automatically calculate this value from the tilt of the surface
3740 : // \autocalculatable
3741 : // \minimum 0.0
3742 : // \maximum 1.0
3743 : // \default autocalculate
3744 : // N2 , \field Number of Vertices
3745 : // \note shown with 120 vertex coordinates -- extensible object
3746 : // \note "extensible" -- duplicate last set of x,y,z coordinates (last 3 fields),
3747 : // \note remembering to remove ; from "inner" fields.
3748 : // \note for clarity in any error messages, renumber the fields as well.
3749 : // \note (and changing z terminator to a comma "," for all but last one which needs a semi-colon ";")
3750 : // \autocalculatable
3751 : // \minimum 3
3752 : // \default autocalculate
3753 : // \note vertices are given in GlobalGeometryRules coordinates -- if relative, all surface coordinates
3754 : // \note are "relative" to the Zone Origin. If world, then building and zone origins are used
3755 : // \note for some internal calculations, but all coordinates are given in an "absolute" system.
3756 : // N3-xx as indicated by the N3 value
3757 :
3758 : // Using/Aliasing
3759 :
3760 : // SUBROUTINE PARAMETER DEFINITIONS:
3761 771 : static Array1D_string const cModuleObjects(4, {"BuildingSurface:Detailed", "Wall:Detailed", "Floor:Detailed", "RoofCeiling:Detailed"});
3762 :
3763 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3764 : int IOStat; // IO Status when calling get input subroutine
3765 : int SurfaceNumAlpha; // Number of material alpha names being passed
3766 : int SurfaceNumProp; // Number of material properties being passed
3767 : int ZoneNum; // DO loop counter (zones)
3768 : int Found; // For matching interzone surfaces
3769 : int Loop;
3770 : int Item;
3771 : int ItemsToGet;
3772 : int ClassItem;
3773 : int ArgPointer;
3774 : int numSides;
3775 :
3776 771 : GetOSCData(state, ErrorsFound);
3777 771 : GetOSCMData(state, ErrorsFound);
3778 771 : GetFoundationData(state, ErrorsFound);
3779 :
3780 771 : NeedToAddSurfaces = 0;
3781 771 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
3782 3855 : for (Item = 1; Item <= 4; ++Item) {
3783 :
3784 3084 : cCurrentModuleObject = cModuleObjects(Item);
3785 3084 : if (Item == 1) {
3786 771 : ItemsToGet = TotHTSurfs;
3787 771 : ClassItem = 0;
3788 2313 : } else if (Item == 2) {
3789 771 : ItemsToGet = TotDetailedWalls;
3790 771 : ClassItem = 1;
3791 1542 : } else if (Item == 3) {
3792 771 : ItemsToGet = TotDetailedFloors;
3793 771 : ClassItem = 2;
3794 : } else { // IF (Item == 4) THEN
3795 771 : ItemsToGet = TotDetailedRoofs;
3796 771 : ClassItem = 3;
3797 : }
3798 :
3799 3084 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, Loop, SurfaceNumAlpha, SurfaceNumProp);
3800 3084 : if (Item == 1) {
3801 771 : if (SurfaceNumAlpha != 9) {
3802 0 : ShowSevereError(
3803 : state,
3804 0 : format("{}: Object Definition indicates not = 9 Alpha Objects, Number Indicated={}", cCurrentModuleObject, SurfaceNumAlpha));
3805 0 : ErrorsFound = true;
3806 : }
3807 : } else {
3808 2313 : if (SurfaceNumAlpha != 8) {
3809 0 : ShowSevereError(
3810 : state,
3811 0 : format("{}: Object Definition indicates not = 8 Alpha Objects, Number Indicated={}", cCurrentModuleObject, SurfaceNumAlpha));
3812 0 : ErrorsFound = true;
3813 : }
3814 : }
3815 :
3816 36095 : for (Loop = 1; Loop <= ItemsToGet; ++Loop) {
3817 231077 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
3818 : cCurrentModuleObject,
3819 : Loop,
3820 33011 : state.dataIPShortCut->cAlphaArgs,
3821 : SurfaceNumAlpha,
3822 33011 : state.dataIPShortCut->rNumericArgs,
3823 : SurfaceNumProp,
3824 : IOStat,
3825 33011 : state.dataIPShortCut->lNumericFieldBlanks,
3826 33011 : state.dataIPShortCut->lAlphaFieldBlanks,
3827 33011 : state.dataIPShortCut->cAlphaFieldNames,
3828 33011 : state.dataIPShortCut->cNumericFieldNames);
3829 :
3830 66022 : if (GlobalNames::VerifyUniqueInterObjectName(state,
3831 33011 : state.dataSurfaceGeometry->UniqueSurfaceNames,
3832 33011 : state.dataIPShortCut->cAlphaArgs(1),
3833 : cCurrentModuleObject,
3834 33011 : state.dataIPShortCut->cAlphaFieldNames(1),
3835 : ErrorsFound)) {
3836 0 : continue;
3837 : }
3838 :
3839 33011 : ++SurfNum;
3840 33011 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name = state.dataIPShortCut->cAlphaArgs(1); // Set the Surface Name in the Derived Type
3841 33011 : ArgPointer = 2;
3842 33011 : if (Item == 1) {
3843 32987 : if (state.dataIPShortCut->cAlphaArgs(2) == "CEILING") state.dataIPShortCut->cAlphaArgs(2) = "ROOF";
3844 32987 : ClassItem = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(2), BaseSurfCls, 3);
3845 32987 : if (ClassItem == 0) {
3846 0 : ShowSevereError(state,
3847 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
3848 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2));
3849 0 : ErrorsFound = true;
3850 : } else {
3851 32987 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = BaseSurfIDs(ClassItem);
3852 : }
3853 32987 : ++ArgPointer;
3854 : } else {
3855 24 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = BaseSurfIDs(ClassItem);
3856 : }
3857 :
3858 99033 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction = UtilityRoutines::FindItemInList(
3859 99033 : state.dataIPShortCut->cAlphaArgs(ArgPointer), state.dataConstruction->Construct, state.dataHeatBal->TotConstructs);
3860 :
3861 33011 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction == 0) {
3862 0 : ErrorsFound = true;
3863 0 : ShowSevereError(state,
3864 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
3865 0 : state.dataIPShortCut->cAlphaFieldNames(ArgPointer) + "=\"" + state.dataIPShortCut->cAlphaArgs(ArgPointer) +
3866 : "\".");
3867 33011 : } else if (state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsWindow) {
3868 0 : ErrorsFound = true;
3869 0 : ShowSevereError(state,
3870 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
3871 0 : state.dataIPShortCut->cAlphaFieldNames(ArgPointer) + "=\"" + state.dataIPShortCut->cAlphaArgs(ArgPointer) +
3872 : "\" - has Window materials.");
3873 0 : if (Item == 1) {
3874 0 : ShowContinueError(state,
3875 0 : "...because " + state.dataIPShortCut->cAlphaFieldNames(2) + '=' + state.dataIPShortCut->cAlphaArgs(2));
3876 : } else {
3877 0 : ShowContinueError(state, "...because Surface Type=" + BaseSurfCls(ClassItem));
3878 : }
3879 : } else {
3880 33011 : state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).IsUsed = true;
3881 33011 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConstructionStoredInputValue =
3882 33011 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction;
3883 : }
3884 33011 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf = true;
3885 33011 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf = SurfNum;
3886 33011 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
3887 :
3888 33011 : ++ArgPointer;
3889 33011 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName = state.dataIPShortCut->cAlphaArgs(ArgPointer);
3890 99033 : ZoneNum = UtilityRoutines::FindItemInList(
3891 99033 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName, state.dataHeatBal->Zone, state.dataGlobal->NumOfZones);
3892 :
3893 33011 : if (ZoneNum != 0) {
3894 33011 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone = ZoneNum;
3895 : } else {
3896 0 : ShowSevereError(state,
3897 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
3898 0 : state.dataIPShortCut->cAlphaFieldNames(ArgPointer) + "=\"" + state.dataIPShortCut->cAlphaArgs(ArgPointer) +
3899 : "\".");
3900 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::Invalid;
3901 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName = "Unknown Zone";
3902 0 : ErrorsFound = true;
3903 : }
3904 :
3905 33011 : ++ArgPointer;
3906 33011 : if (!state.dataIPShortCut->lAlphaFieldBlanks(ArgPointer)) {
3907 25 : int spaceNum = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(ArgPointer), state.dataHeatBal->space);
3908 :
3909 25 : if (spaceNum != 0) {
3910 25 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).spaceNum = spaceNum;
3911 25 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone != state.dataHeatBal->space(spaceNum).zoneNum) {
3912 0 : ShowSevereError(state,
3913 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
3914 0 : state.dataIPShortCut->cAlphaFieldNames(ArgPointer) + "=\"" +
3915 0 : state.dataIPShortCut->cAlphaArgs(ArgPointer) + "\" is not in the same zone as the surface.");
3916 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::Invalid;
3917 0 : ErrorsFound = true;
3918 : }
3919 : } else {
3920 0 : ShowSevereError(state,
3921 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
3922 0 : state.dataIPShortCut->cAlphaFieldNames(ArgPointer) + "=\"" +
3923 0 : state.dataIPShortCut->cAlphaArgs(ArgPointer) + "\" not found.");
3924 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::Invalid;
3925 0 : ErrorsFound = true;
3926 : }
3927 : }
3928 : // Get the ExteriorBoundaryCondition flag from input There are 4 conditions that
3929 : // can take place. The conditions are set with a 0, -1, or -2, or all of the
3930 : // zone names have to be looked at and generate the interzone array number
3931 33011 : ++ArgPointer;
3932 33011 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataIPShortCut->cAlphaArgs(ArgPointer + 1);
3933 :
3934 33011 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "Outdoors")) {
3935 10666 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = ExternalEnvironment;
3936 :
3937 22345 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "Adiabatic")) {
3938 1259 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = UnreconciledZoneSurface;
3939 1259 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
3940 :
3941 21086 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "Ground")) {
3942 2110 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = Ground;
3943 :
3944 2110 : if (state.dataSurfaceGeometry->NoGroundTempObjWarning) {
3945 421 : if (!state.dataEnvrn->GroundTempObjInput) {
3946 1 : ShowWarningError(state,
3947 : "GetHTSurfaceData: Surfaces with interface to Ground found but no \"Ground Temperatures\" were input.");
3948 1 : ShowContinueError(state, "Found first in surface=" + state.dataIPShortCut->cAlphaArgs(1));
3949 3 : ShowContinueError(
3950 2 : state, format("Defaults, constant throughout the year of ({:.1R}) will be used.", state.dataEnvrn->GroundTemp));
3951 : }
3952 421 : state.dataSurfaceGeometry->NoGroundTempObjWarning = false;
3953 : }
3954 :
3955 : // Added for FCfactor method
3956 18976 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "GroundFCfactorMethod")) {
3957 179 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = GroundFCfactorMethod;
3958 179 : if (state.dataSurfaceGeometry->NoFCGroundTempObjWarning) {
3959 179 : if (!state.dataEnvrn->FCGroundTemps) {
3960 0 : ShowSevereError(state,
3961 : "GetHTSurfaceData: Surfaces with interface to GroundFCfactorMethod found but no \"FC Ground "
3962 : "Temperatures\" were input.");
3963 0 : ShowContinueError(state, "Found first in surface=" + state.dataIPShortCut->cAlphaArgs(1));
3964 0 : ShowContinueError(state,
3965 : "Either add a \"Site:GroundTemperature:FCfactorMethod\" object or use a weather file with "
3966 : "Ground Temperatures.");
3967 0 : ErrorsFound = true;
3968 0 : state.dataSurfaceGeometry->NoFCGroundTempObjWarning = false;
3969 : }
3970 : }
3971 179 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction > 0) {
3972 213 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Wall &&
3973 34 : !state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsCfactorWall) {
3974 0 : ShowSevereError(state,
3975 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
3976 0 : state.dataIPShortCut->cAlphaFieldNames(ArgPointer));
3977 0 : ShowContinueError(
3978 : state,
3979 0 : "Construction=\"" +
3980 0 : state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).Name +
3981 : "\" is not type Construction:CfactorUndergroundWall.");
3982 0 : ErrorsFound = true;
3983 : }
3984 324 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Floor &&
3985 145 : !state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsFfactorFloor) {
3986 0 : ShowSevereError(state,
3987 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
3988 0 : state.dataIPShortCut->cAlphaFieldNames(ArgPointer));
3989 0 : ShowContinueError(
3990 : state,
3991 0 : "Construction=\"" +
3992 0 : state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).Name +
3993 : "\" is not type Construction:FfactorGroundFloor.");
3994 0 : ErrorsFound = true;
3995 : }
3996 : }
3997 :
3998 18797 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "OtherSideCoefficients")) {
3999 51 : Found = UtilityRoutines::FindItemInList(
4000 51 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName, state.dataSurface->OSC, state.dataSurface->TotOSC);
4001 17 : if (Found == 0) {
4002 0 : ShowSevereError(state,
4003 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
4004 0 : state.dataIPShortCut->cAlphaFieldNames(ArgPointer + 1) + "=\"" +
4005 0 : state.dataIPShortCut->cAlphaArgs(ArgPointer + 1) + "\".");
4006 0 : ShowContinueError(state, " no OtherSideCoefficients of that name.");
4007 0 : ErrorsFound = true;
4008 : } else {
4009 17 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OSCPtr = Found;
4010 17 : if (state.dataSurface->OSC(Found).SurfFilmCoef > 0.0) {
4011 1 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = OtherSideCoefCalcExt;
4012 : } else {
4013 16 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = OtherSideCoefNoCalcExt;
4014 : }
4015 : }
4016 :
4017 18780 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "Surface")) {
4018 : // it has to be another surface which needs to be found
4019 : // this will be found on the second pass through the surface input
4020 : // for flagging, set the value to UnreconciledZoneSurface
4021 : // name (ExtBoundCondName) will be validated later.
4022 18337 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = UnreconciledZoneSurface;
4023 18337 : if (state.dataIPShortCut->lAlphaFieldBlanks(ArgPointer + 1)) {
4024 6 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
4025 18 : ShowSevereError(state,
4026 12 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
4027 18 : state.dataIPShortCut->cAlphaFieldNames(ArgPointer + 1) + "=<blank>.");
4028 6 : ShowContinueError(state, ".." + state.dataIPShortCut->cAlphaFieldNames(ArgPointer) + "=\"Surface\" must be non-blank.");
4029 6 : ShowContinueError(state, "..This surface will become an adiabatic surface - no doors/windows allowed.");
4030 : }
4031 :
4032 443 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "Zone")) {
4033 : // This is the code for an unmatched "other surface"
4034 : // will be set up later.
4035 363 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = UnenteredAdjacentZoneSurface;
4036 : // check OutsideFaceEnvironment for legal zone
4037 1089 : Found = UtilityRoutines::FindItemInList(
4038 1089 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName, state.dataHeatBal->Zone, state.dataGlobal->NumOfZones);
4039 363 : ++NeedToAddSurfaces;
4040 :
4041 363 : if (Found == 0) {
4042 0 : ShowSevereError(state,
4043 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
4044 0 : state.dataIPShortCut->cAlphaFieldNames(ArgPointer) + "=\"" +
4045 0 : state.dataIPShortCut->cAlphaArgs(ArgPointer) + "\".");
4046 0 : ShowContinueError(state, "..Referenced as Zone for this surface.");
4047 0 : ErrorsFound = true;
4048 : }
4049 :
4050 80 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "Foundation")) {
4051 :
4052 38 : if (!state.dataWeatherManager->WeatherFileExists) {
4053 0 : ShowSevereError(state,
4054 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
4055 : "\", using \"Foundation\" type Outside Boundary Condition requires specification of a weather file");
4056 0 : ShowContinueError(state,
4057 : "Either place in.epw in the working directory or specify a weather file on the command line using -w "
4058 : "/path/to/weather.epw");
4059 0 : ErrorsFound = true;
4060 : }
4061 :
4062 : // Find foundation object, if blank use default
4063 38 : if (state.dataIPShortCut->lAlphaFieldBlanks(ArgPointer + 1)) {
4064 :
4065 8 : if (!state.dataSurfaceGeometry->kivaManager.defaultAdded) {
4066 : // Add default foundation if no other foundation object specified
4067 2 : state.dataSurfaceGeometry->kivaManager.addDefaultFoundation();
4068 : }
4069 8 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OSCPtr =
4070 8 : state.dataSurfaceGeometry->kivaManager.defaultIndex; // Reuse OSC pointer...shouldn't be used for non OSC surfaces anyway.
4071 : } else {
4072 30 : Found =
4073 30 : state.dataSurfaceGeometry->kivaManager.findFoundation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName);
4074 30 : if (Found != (int)state.dataSurfaceGeometry->kivaManager.foundationInputs.size()) {
4075 30 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OSCPtr = Found;
4076 : } else {
4077 0 : ShowSevereError(state,
4078 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
4079 0 : state.dataIPShortCut->cAlphaFieldNames(ArgPointer + 1) + "=\"" +
4080 0 : state.dataIPShortCut->cAlphaArgs(ArgPointer + 1) + "\".");
4081 0 : ErrorsFound = true;
4082 : }
4083 : }
4084 :
4085 38 : if (state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).SourceSinkPresent) {
4086 0 : ShowSevereError(state,
4087 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
4088 : "\", construction may not have an internal source/sink");
4089 0 : ErrorsFound = true;
4090 : }
4091 38 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = KivaFoundation;
4092 :
4093 42 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "OtherSideConditionsModel")) {
4094 126 : Found = UtilityRoutines::FindItemInList(
4095 126 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName, state.dataSurface->OSCM, state.dataSurface->TotOSCM);
4096 42 : if (Found == 0) {
4097 0 : ShowSevereError(state,
4098 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
4099 0 : state.dataIPShortCut->cAlphaFieldNames(ArgPointer + 1) + "=\"" +
4100 0 : state.dataIPShortCut->cAlphaArgs(ArgPointer + 1) + "\".");
4101 0 : ErrorsFound = true;
4102 : }
4103 42 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OSCMPtr = Found;
4104 42 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = OtherSideCondModeledExt;
4105 :
4106 0 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "GroundSlabPreprocessorAverage") ||
4107 0 : UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "GroundSlabPreprocessorCore") ||
4108 0 : UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "GroundSlabPreprocessorPerimeter") ||
4109 0 : UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "GroundBasementPreprocessorAverageFloor") ||
4110 0 : UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "GroundBasementPreprocessorAverageWall") ||
4111 0 : UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "GroundBasementPreprocessorUpperWall") ||
4112 0 : UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "GroundBasementPreprocessorLowerWall")) {
4113 0 : ShowSevereError(state,
4114 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
4115 0 : state.dataIPShortCut->cAlphaFieldNames(ArgPointer) + "=\"" + state.dataIPShortCut->cAlphaArgs(ArgPointer) +
4116 : "\".");
4117 0 : ShowContinueError(state, "The ExpandObjects program has not been run or is not in your EnergyPlus.exe folder.");
4118 0 : ErrorsFound = true;
4119 :
4120 : } else {
4121 0 : ShowSevereError(state,
4122 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
4123 0 : state.dataIPShortCut->cAlphaFieldNames(ArgPointer) + "=\"" + state.dataIPShortCut->cAlphaArgs(ArgPointer) +
4124 : "\".");
4125 0 : ShowContinueError(state,
4126 : "Should be one of \"Outdoors\", \"Adiabatic\", Ground\", \"Surface\", \"OtherSideCoefficients\", "
4127 : "\"OtherSideConditionsModel\" or \"Zone\"");
4128 0 : ErrorsFound = true;
4129 : } // ... End of the ExtBoundCond logical IF Block
4130 :
4131 33011 : ArgPointer += 2;
4132 : // Set the logical flag for the exterior solar
4133 33011 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "SunExposed")) {
4134 10574 : if ((state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond != ExternalEnvironment) &&
4135 16 : (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond != OtherSideCondModeledExt)) {
4136 0 : ShowWarningError(state,
4137 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", " +
4138 0 : state.dataIPShortCut->cAlphaFieldNames(ArgPointer) + "=\"" +
4139 0 : state.dataIPShortCut->cAlphaArgs(ArgPointer) + "\".");
4140 0 : ShowContinueError(state, "..This surface is not exposed to External Environment. Sun exposure has no effect.");
4141 : } else {
4142 10558 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar = true;
4143 : }
4144 22453 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "NoSun")) {
4145 22453 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar = false;
4146 : } else {
4147 0 : ShowSevereError(state,
4148 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
4149 0 : state.dataIPShortCut->cAlphaFieldNames(ArgPointer) + "=\"" + state.dataIPShortCut->cAlphaArgs(ArgPointer) +
4150 : "\".");
4151 0 : ErrorsFound = true;
4152 : }
4153 :
4154 33011 : ++ArgPointer;
4155 : // Set the logical flag for the exterior wind
4156 33011 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "WindExposed")) {
4157 10626 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtWind = true;
4158 22385 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(ArgPointer), "NoWind")) {
4159 22385 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtWind = false;
4160 : } else {
4161 0 : ShowSevereError(state,
4162 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
4163 0 : state.dataIPShortCut->cAlphaFieldNames(ArgPointer) + "=\"" + state.dataIPShortCut->cAlphaArgs(ArgPointer) +
4164 : "\".");
4165 0 : ErrorsFound = true;
4166 : }
4167 :
4168 : // Set the logical flag for the EcoRoof presented, this is only based on the flag in the construction type
4169 : // if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction > 0)
4170 : // state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtEcoRoof =
4171 : // state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsEcoRoof;
4172 :
4173 33011 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGround = state.dataIPShortCut->rNumericArgs(1);
4174 33011 : if (state.dataIPShortCut->lNumericFieldBlanks(1))
4175 142 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGround = DataGlobalConstants::AutoCalculate;
4176 33011 : if (state.dataIPShortCut->lNumericFieldBlanks(2) || state.dataIPShortCut->rNumericArgs(2) == DataGlobalConstants::AutoCalculate) {
4177 263 : numSides = (SurfaceNumProp - 2) / 3;
4178 263 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = numSides;
4179 263 : if (mod(SurfaceNumProp - 2, 3) != 0) {
4180 0 : ShowWarningError(state,
4181 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", " +
4182 0 : format("{} not even multiple of 3. Will read in {}",
4183 0 : state.dataIPShortCut->cNumericFieldNames(2),
4184 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides));
4185 : }
4186 263 : if (numSides < 3) {
4187 0 : ShowSevereError(state,
4188 0 : format("{}=\"{}\", {} (autocalculate) must be >= 3. Only {} provided.",
4189 : cCurrentModuleObject,
4190 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
4191 0 : state.dataIPShortCut->cNumericFieldNames(2),
4192 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides));
4193 0 : ErrorsFound = true;
4194 0 : continue;
4195 : }
4196 : } else {
4197 32748 : numSides = (SurfaceNumProp - 2) / 3;
4198 32748 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = state.dataIPShortCut->rNumericArgs(2);
4199 32748 : if (numSides > state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides) {
4200 0 : ShowWarningError(state,
4201 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", field " +
4202 0 : state.dataIPShortCut->cNumericFieldNames(2) + '=' +
4203 0 : fmt::to_string(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides));
4204 0 : ShowContinueError(state,
4205 0 : format("...but {} were entered. Only the indicated {} will be used.",
4206 : numSides,
4207 0 : state.dataIPShortCut->cNumericFieldNames(2)));
4208 : }
4209 : }
4210 33011 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.allocate(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
4211 33011 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewVertex.allocate(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
4212 33011 : GetVertices(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides, state.dataIPShortCut->rNumericArgs({3, _}));
4213 33011 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area <= 0.0) {
4214 0 : ShowSevereError(state,
4215 0 : format("{}=\"{}\", Surface Area <= 0.0; Entered Area={:.2T}",
4216 : cCurrentModuleObject,
4217 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
4218 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area));
4219 0 : ErrorsFound = true;
4220 : }
4221 :
4222 33011 : CheckConvexity(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
4223 33011 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(5), "Surface")) {
4224 16 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides !=
4225 8 : static_cast<int>(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.size())) {
4226 0 : ShowSevereError(state,
4227 0 : format("{}=\"{}\", After CheckConvexity, mismatch between Sides ({}) and size of Vertex ({}).",
4228 : cCurrentModuleObject,
4229 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
4230 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
4231 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.size()));
4232 0 : ShowContinueError(state, "CheckConvexity is used to verify the convexity of a surface and detect collinear points.");
4233 0 : ErrorsFound = true;
4234 : }
4235 : }
4236 33011 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction > 0) {
4237 : // Check wall height for the CFactor walls
4238 :
4239 54160 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Wall &&
4240 21149 : state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsCfactorWall) {
4241 102 : if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Height -
4242 68 : state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).Height) > 0.05) {
4243 0 : ShowWarningError(state,
4244 0 : format("{}=\"{}\", underground Wall Height = {:.2T}",
4245 : cCurrentModuleObject,
4246 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
4247 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Height));
4248 0 : ShowContinueError(state, "..which does not match its construction height.");
4249 : }
4250 : }
4251 :
4252 : // Check area and perimeter for the FFactor floors
4253 39418 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Floor &&
4254 6407 : state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsFfactorFloor) {
4255 537 : if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area -
4256 358 : state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).Area) > 0.1) {
4257 0 : ShowWarningError(state,
4258 0 : format("{}=\"{}\", underground Floor Area = {:.2T}",
4259 : cCurrentModuleObject,
4260 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
4261 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area));
4262 0 : ShowContinueError(state, "..which does not match its construction area.");
4263 : }
4264 358 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Perimeter <
4265 179 : state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).PerimeterExposed - 0.1) {
4266 0 : ShowWarningError(state,
4267 0 : format("{}=\"{}\", underground Floor Perimeter = {:.2T}",
4268 : cCurrentModuleObject,
4269 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
4270 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Perimeter));
4271 0 : ShowContinueError(state, "..which is less than its construction exposed perimeter.");
4272 : }
4273 : }
4274 : }
4275 : }
4276 : } // Item Looop
4277 : // Check number of Vertex between base surface and Outside Boundary surface
4278 : int ExtSurfNum;
4279 33922 : for (int i = 1; i <= SurfNum; i++) {
4280 52747 : if (state.dataSurfaceGeometry->SurfaceTmp(i).ExtBoundCond == UnreconciledZoneSurface &&
4281 19596 : state.dataSurfaceGeometry->SurfaceTmp(i).ExtBoundCondName != "") {
4282 19596 : ExtSurfNum =
4283 19596 : UtilityRoutines::FindItemInList(state.dataSurfaceGeometry->SurfaceTmp(i).ExtBoundCondName, state.dataSurfaceGeometry->SurfaceTmp);
4284 : // If we cannot find the referenced surface
4285 19596 : if (ExtSurfNum == 0) {
4286 0 : ShowSevereError(state,
4287 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(i).Name +
4288 0 : "\" references an outside boundary surface that cannot be found:" +
4289 0 : state.dataSurfaceGeometry->SurfaceTmp(i).ExtBoundCondName);
4290 0 : ErrorsFound = true;
4291 : // If vertex size mistmatch
4292 39192 : } else if (state.dataSurfaceGeometry->SurfaceTmp(i).Vertex.size() !=
4293 19596 : state.dataSurfaceGeometry->SurfaceTmp(ExtSurfNum).Vertex.size()) {
4294 0 : ShowSevereError(state,
4295 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(i).Name +
4296 0 : "\", Vertex size mismatch between base surface :" + state.dataSurfaceGeometry->SurfaceTmp(i).Name +
4297 0 : " and outside boundary surface: " + state.dataSurfaceGeometry->SurfaceTmp(ExtSurfNum).Name);
4298 0 : ShowContinueError(state,
4299 0 : format("The vertex sizes are {} for base surface and {} for outside boundary surface. Please check inputs.",
4300 0 : state.dataSurfaceGeometry->SurfaceTmp(i).Vertex.size(),
4301 0 : state.dataSurfaceGeometry->SurfaceTmp(ExtSurfNum).Vertex.size()));
4302 0 : ErrorsFound = true;
4303 : }
4304 : }
4305 : }
4306 771 : }
4307 :
4308 771 : void GetRectSurfaces(EnergyPlusData &state,
4309 : bool &ErrorsFound, // Error flag indicator (true if errors found)
4310 : int &SurfNum, // Count of Current SurfaceNumber
4311 : int const TotRectExtWalls, // Number of Exterior Walls to obtain
4312 : int const TotRectIntWalls, // Number of Adiabatic Walls to obtain
4313 : int const TotRectIZWalls, // Number of Interzone Walls to obtain
4314 : int const TotRectUGWalls, // Number of Underground to obtain
4315 : int const TotRectRoofs, // Number of Roofs to obtain
4316 : int const TotRectCeilings, // Number of Adiabatic Ceilings to obtain
4317 : int const TotRectIZCeilings, // Number of Interzone Ceilings to obtain
4318 : int const TotRectGCFloors, // Number of Floors with Ground Contact to obtain
4319 : int const TotRectIntFloors, // Number of Adiabatic Walls to obtain
4320 : int const TotRectIZFloors, // Number of Interzone Floors to obtain
4321 : const Array1D<SurfaceClass> &BaseSurfIDs, // ID Assignments for valid surface classes
4322 : int &NeedToAddSurfaces // Number of surfaces to add, based on unentered IZ surfaces
4323 : )
4324 : {
4325 :
4326 : // SUBROUTINE INFORMATION:
4327 : // AUTHOR Linda Lawrie
4328 : // DATE WRITTEN December 2008
4329 : // MODIFIED na
4330 : // RE-ENGINEERED na
4331 :
4332 : // PURPOSE OF THIS SUBROUTINE:
4333 : // Get simple (rectangular, LLC corner specified) walls
4334 :
4335 : // Using/Aliasing
4336 :
4337 : // SUBROUTINE PARAMETER DEFINITIONS:
4338 : static Array1D_string const cModuleObjects(10,
4339 : {"Wall:Exterior",
4340 : "Wall:Adiabatic",
4341 : "Wall:Interzone",
4342 : "Wall:Underground",
4343 : "Roof",
4344 : "Ceiling:Adiabatic",
4345 : "Ceiling:Interzone",
4346 : "Floor:GroundContact",
4347 : "Floor:Adiabatic",
4348 771 : "Floor:Interzone"});
4349 :
4350 : int Item;
4351 : int ItemsToGet;
4352 : int Loop;
4353 : int NumAlphas;
4354 : int NumNumbers;
4355 : int IOStat; // IO Status when calling get input subroutine
4356 : int Found; // For matching base surfaces
4357 : bool GettingIZSurfaces;
4358 : int OtherSurfaceField;
4359 : int ExtBoundCondition;
4360 : int ClassItem;
4361 : int ZoneNum;
4362 771 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
4363 8481 : for (Item = 1; Item <= 10; ++Item) {
4364 :
4365 7710 : cCurrentModuleObject = cModuleObjects(Item);
4366 7710 : if (Item == 1) {
4367 771 : ItemsToGet = TotRectExtWalls;
4368 771 : GettingIZSurfaces = false;
4369 771 : OtherSurfaceField = 0;
4370 771 : ExtBoundCondition = ExternalEnvironment;
4371 771 : ClassItem = 1;
4372 6939 : } else if (Item == 2) {
4373 771 : ItemsToGet = TotRectIntWalls;
4374 771 : GettingIZSurfaces = false;
4375 771 : OtherSurfaceField = 0;
4376 771 : ExtBoundCondition = UnreconciledZoneSurface;
4377 771 : ClassItem = 1;
4378 6168 : } else if (Item == 3) {
4379 771 : ItemsToGet = TotRectIZWalls;
4380 771 : GettingIZSurfaces = true;
4381 771 : OtherSurfaceField = 5;
4382 771 : ExtBoundCondition = UnreconciledZoneSurface;
4383 771 : ClassItem = 1;
4384 5397 : } else if (Item == 4) {
4385 771 : ItemsToGet = TotRectUGWalls;
4386 771 : GettingIZSurfaces = false;
4387 771 : OtherSurfaceField = 0;
4388 771 : ExtBoundCondition = Ground;
4389 771 : ClassItem = 1;
4390 4626 : } else if (Item == 5) {
4391 771 : ItemsToGet = TotRectRoofs;
4392 771 : GettingIZSurfaces = false;
4393 771 : OtherSurfaceField = 0;
4394 771 : ExtBoundCondition = ExternalEnvironment;
4395 771 : ClassItem = 3;
4396 3855 : } else if (Item == 6) {
4397 771 : ItemsToGet = TotRectCeilings;
4398 771 : GettingIZSurfaces = false;
4399 771 : OtherSurfaceField = 0;
4400 771 : ExtBoundCondition = UnreconciledZoneSurface;
4401 771 : ClassItem = 3;
4402 3084 : } else if (Item == 7) {
4403 771 : ItemsToGet = TotRectIZCeilings;
4404 771 : GettingIZSurfaces = false;
4405 771 : OtherSurfaceField = 5;
4406 771 : ExtBoundCondition = UnreconciledZoneSurface;
4407 771 : ClassItem = 3;
4408 2313 : } else if (Item == 8) {
4409 771 : ItemsToGet = TotRectGCFloors;
4410 771 : GettingIZSurfaces = false;
4411 771 : OtherSurfaceField = 0;
4412 771 : ExtBoundCondition = Ground;
4413 771 : ClassItem = 2;
4414 1542 : } else if (Item == 9) {
4415 771 : ItemsToGet = TotRectIntFloors;
4416 771 : GettingIZSurfaces = false;
4417 771 : OtherSurfaceField = 0;
4418 771 : ExtBoundCondition = UnreconciledZoneSurface;
4419 771 : ClassItem = 2;
4420 : } else { // IF (Item == 10) THEN
4421 771 : ItemsToGet = TotRectIZFloors;
4422 771 : GettingIZSurfaces = true;
4423 771 : OtherSurfaceField = 5;
4424 771 : ExtBoundCondition = UnreconciledZoneSurface;
4425 771 : ClassItem = 2;
4426 : }
4427 :
4428 7829 : for (Loop = 1; Loop <= ItemsToGet; ++Loop) {
4429 833 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
4430 : cCurrentModuleObject,
4431 : Loop,
4432 119 : state.dataIPShortCut->cAlphaArgs,
4433 : NumAlphas,
4434 119 : state.dataIPShortCut->rNumericArgs,
4435 : NumNumbers,
4436 : IOStat,
4437 119 : state.dataIPShortCut->lNumericFieldBlanks,
4438 119 : state.dataIPShortCut->lAlphaFieldBlanks,
4439 119 : state.dataIPShortCut->cAlphaFieldNames,
4440 119 : state.dataIPShortCut->cNumericFieldNames);
4441 :
4442 238 : if (GlobalNames::VerifyUniqueInterObjectName(state,
4443 119 : state.dataSurfaceGeometry->UniqueSurfaceNames,
4444 119 : state.dataIPShortCut->cAlphaArgs(1),
4445 : cCurrentModuleObject,
4446 119 : state.dataIPShortCut->cAlphaFieldNames(1),
4447 : ErrorsFound)) {
4448 0 : continue;
4449 : }
4450 :
4451 119 : if (NumNumbers < 7) {
4452 0 : ShowSevereError(state,
4453 0 : format("{}=\"{}\", Too few number of numeric args=[{}].",
4454 : cCurrentModuleObject,
4455 0 : state.dataIPShortCut->cAlphaArgs(1),
4456 0 : NumNumbers));
4457 0 : ErrorsFound = true;
4458 : }
4459 :
4460 119 : ++SurfNum;
4461 119 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name = state.dataIPShortCut->cAlphaArgs(1); // Set the Surface Name in the Derived Type
4462 119 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = BaseSurfIDs(ClassItem); // Set class number
4463 :
4464 357 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction = UtilityRoutines::FindItemInList(
4465 357 : state.dataIPShortCut->cAlphaArgs(2), state.dataConstruction->Construct, state.dataHeatBal->TotConstructs);
4466 :
4467 119 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction == 0) {
4468 0 : ErrorsFound = true;
4469 0 : ShowSevereError(state,
4470 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
4471 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) + "\".");
4472 119 : } else if (state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsWindow) {
4473 0 : ErrorsFound = true;
4474 0 : ShowSevereError(state,
4475 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
4476 0 : state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) +
4477 : "\" - has Window materials.");
4478 0 : ShowContinueError(state, "...because " + state.dataIPShortCut->cAlphaFieldNames(2) + '=' + state.dataIPShortCut->cAlphaArgs(2));
4479 : } else {
4480 119 : state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).IsUsed = true;
4481 119 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConstructionStoredInputValue =
4482 119 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction;
4483 : }
4484 119 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf = true;
4485 119 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf = SurfNum;
4486 119 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
4487 :
4488 119 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName = state.dataIPShortCut->cAlphaArgs(3);
4489 357 : ZoneNum = UtilityRoutines::FindItemInList(
4490 357 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName, state.dataHeatBal->Zone, state.dataGlobal->NumOfZones);
4491 :
4492 119 : if (ZoneNum != 0) {
4493 119 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone = ZoneNum;
4494 : } else {
4495 0 : ShowSevereError(state,
4496 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
4497 0 : state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) + "\".");
4498 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::Invalid;
4499 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName = "Unknown Zone";
4500 0 : ErrorsFound = true;
4501 : }
4502 :
4503 119 : if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) {
4504 0 : int spaceNum = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(4), state.dataHeatBal->space);
4505 :
4506 0 : if (spaceNum != 0) {
4507 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).spaceNum = spaceNum;
4508 : } else {
4509 0 : ShowSevereError(state,
4510 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
4511 0 : state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\".");
4512 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::Invalid;
4513 0 : ErrorsFound = true;
4514 : }
4515 : }
4516 :
4517 119 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = ExtBoundCondition;
4518 119 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction > 0) {
4519 317 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Wall &&
4520 119 : state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsCfactorWall &&
4521 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == Ground) {
4522 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = GroundFCfactorMethod;
4523 119 : } else if (state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsCfactorWall) {
4524 0 : ErrorsFound = true;
4525 0 : ShowSevereError(state,
4526 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
4527 : "\", Construction type is \"Construction:CfactorUndergroundWall\" but invalid for this object.");
4528 : }
4529 258 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Floor &&
4530 119 : state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsFfactorFloor &&
4531 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == Ground) {
4532 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = GroundFCfactorMethod;
4533 119 : } else if (state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsFfactorFloor) {
4534 0 : ErrorsFound = true;
4535 0 : ShowSevereError(state,
4536 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
4537 : "\", Construction type is \"Construction:FfactorGroundFloor\" but invalid for this object.");
4538 : }
4539 : }
4540 119 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar = false;
4541 119 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtWind = false;
4542 119 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGround = DataGlobalConstants::AutoCalculate;
4543 :
4544 119 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == ExternalEnvironment) {
4545 66 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar = true;
4546 66 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtWind = true;
4547 :
4548 : // Set the logical flag for the EcoRoof presented, this is only based on the flag in the construction type
4549 : // if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction > 0)
4550 : // state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtEcoRoof =
4551 : // state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsEcoRoof;
4552 :
4553 53 : } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnreconciledZoneSurface) {
4554 47 : if (GettingIZSurfaces) {
4555 19 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataIPShortCut->cAlphaArgs(OtherSurfaceField);
4556 57 : Found = UtilityRoutines::FindItemInList(
4557 57 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName, state.dataHeatBal->Zone, state.dataGlobal->NumOfZones);
4558 : // see if match to zone, then it's an unentered other surface, else reconciled later
4559 19 : if (Found > 0) {
4560 1 : ++NeedToAddSurfaces;
4561 1 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = UnenteredAdjacentZoneSurface;
4562 : }
4563 : } else {
4564 28 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
4565 : }
4566 :
4567 6 : } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == Ground) {
4568 :
4569 6 : if (state.dataSurfaceGeometry->NoGroundTempObjWarning) {
4570 1 : if (!state.dataEnvrn->GroundTempObjInput) {
4571 0 : ShowWarningError(state,
4572 : "GetRectSurfaces: Surfaces with interface to Ground found but no \"Ground Temperatures\" were input.");
4573 0 : ShowContinueError(state, "Found first in surface=" + state.dataIPShortCut->cAlphaArgs(1));
4574 0 : ShowContinueError(
4575 0 : state, format("Defaults, constant throughout the year of ({:.1R}) will be used.", state.dataEnvrn->GroundTemp));
4576 : }
4577 1 : state.dataSurfaceGeometry->NoGroundTempObjWarning = false;
4578 : }
4579 :
4580 0 : } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == GroundFCfactorMethod) {
4581 0 : if (state.dataSurfaceGeometry->NoFCGroundTempObjWarning) {
4582 0 : if (!state.dataEnvrn->FCGroundTemps) {
4583 0 : ShowSevereError(state,
4584 : "GetRectSurfaces: Surfaces with interface to GroundFCfactorMethod found but no \"FC Ground "
4585 : "Temperatures\" were input.");
4586 0 : ShowContinueError(state, "Found first in surface=" + state.dataIPShortCut->cAlphaArgs(1));
4587 0 : ShowContinueError(state,
4588 : "Either add a \"Site:GroundTemperature:FCfactorMethod\" object or use a weather file with "
4589 : "Ground Temperatures.");
4590 0 : ErrorsFound = true;
4591 0 : state.dataSurfaceGeometry->NoFCGroundTempObjWarning = false;
4592 : }
4593 : }
4594 :
4595 : } // ... End of the ExtBoundCond logical IF Block
4596 :
4597 119 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth = state.dataIPShortCut->rNumericArgs(1);
4598 119 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt = state.dataIPShortCut->rNumericArgs(2);
4599 119 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConvOrientation =
4600 119 : ConvectionCoefficients::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
4601 119 : if (!state.dataSurface->WorldCoordSystem) {
4602 95 : if (ZoneNum != 0) {
4603 95 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth +=
4604 95 : state.dataHeatBal->BuildingAzimuth + state.dataHeatBal->Zone(ZoneNum).RelNorth;
4605 : }
4606 : }
4607 119 : if (ZoneNum != 0) {
4608 119 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth += state.dataHeatBal->BuildingRotationAppendixG;
4609 : }
4610 :
4611 119 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = 4;
4612 119 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.allocate(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
4613 :
4614 714 : MakeRectangularVertices(state,
4615 : SurfNum,
4616 119 : state.dataIPShortCut->rNumericArgs(3),
4617 119 : state.dataIPShortCut->rNumericArgs(4),
4618 119 : state.dataIPShortCut->rNumericArgs(5),
4619 119 : state.dataIPShortCut->rNumericArgs(6),
4620 119 : state.dataIPShortCut->rNumericArgs(7),
4621 119 : state.dataSurfaceGeometry->RectSurfRefWorldCoordSystem);
4622 :
4623 119 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area <= 0.0) {
4624 0 : ShowSevereError(state,
4625 0 : format("{}=\"{}\", Surface Area <= 0.0; Entered Area={:.2T}",
4626 : cCurrentModuleObject,
4627 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
4628 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area));
4629 0 : ErrorsFound = true;
4630 : }
4631 :
4632 : // Check wall height for the CFactor walls
4633 198 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Wall &&
4634 79 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == GroundFCfactorMethod) {
4635 0 : if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Height -
4636 0 : state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).Height) > 0.05) {
4637 0 : ShowWarningError(state,
4638 0 : format("{}=\"{}\", underground Wall Height = {:.2T}",
4639 : cCurrentModuleObject,
4640 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
4641 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Height));
4642 0 : ShowContinueError(state, "..which deos not match its construction height.");
4643 : }
4644 : }
4645 :
4646 : // Check area and perimeter for the FFactor floors
4647 139 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Floor &&
4648 20 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == GroundFCfactorMethod) {
4649 0 : if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area -
4650 0 : state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).Area) > 0.1) {
4651 0 : ShowWarningError(state,
4652 0 : format("{}=\"{}\", underground Floor Area = {:.2T}",
4653 : cCurrentModuleObject,
4654 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
4655 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area));
4656 0 : ShowContinueError(state, "..which does not match its construction area.");
4657 : }
4658 0 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Perimeter <
4659 0 : state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).PerimeterExposed - 0.1) {
4660 0 : ShowWarningError(state,
4661 0 : format("{}=\"{}\", underground Floor Perimeter = {:.2T}",
4662 : cCurrentModuleObject,
4663 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
4664 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Perimeter));
4665 0 : ShowContinueError(state, "..which is less than its construction exposed perimeter.");
4666 : }
4667 : }
4668 : } // Getting Items
4669 : }
4670 771 : }
4671 :
4672 139 : void MakeRectangularVertices(EnergyPlusData &state,
4673 : int const SurfNum,
4674 : Real64 const XCoord,
4675 : Real64 const YCoord,
4676 : Real64 const ZCoord,
4677 : Real64 const Length,
4678 : Real64 const Height,
4679 : bool const SurfWorldCoordSystem)
4680 : {
4681 :
4682 : // SUBROUTINE INFORMATION:
4683 : // AUTHOR Linda Lawrie
4684 : // DATE WRITTEN December 2008
4685 : // MODIFIED na
4686 : // RE-ENGINEERED na
4687 :
4688 : // PURPOSE OF THIS SUBROUTINE:
4689 : // This routine creates world/3d coordinates for rectangular surfaces using azimuth, tilt, LLC (X,Y,Z), length & height.
4690 :
4691 : // METHODOLOGY EMPLOYED:
4692 : // na
4693 :
4694 : // REFERENCES:
4695 : // na
4696 :
4697 : // Using/Aliasing
4698 : using namespace Vectors;
4699 :
4700 : // Locals
4701 : // SUBROUTINE ARGUMENT DEFINITIONS:
4702 :
4703 : // SUBROUTINE PARAMETER DEFINITIONS:
4704 : // na
4705 :
4706 : // INTERFACE BLOCK SPECIFICATIONS:
4707 : // na
4708 :
4709 : // DERIVED TYPE DEFINITIONS:
4710 : // na
4711 :
4712 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
4713 : Real64 SurfAzimuth; // Surface Azimuth/Facing (same as Base Surface)
4714 : Real64 SurfTilt; // Tilt (same as Base Surface)
4715 : Real64 XLLC;
4716 : Real64 YLLC;
4717 : Real64 ZLLC;
4718 : Real64 CosSurfAzimuth;
4719 : Real64 SinSurfAzimuth;
4720 : Real64 CosSurfTilt;
4721 : Real64 SinSurfTilt;
4722 278 : Array1D<Real64> XX(4);
4723 278 : Array1D<Real64> YY(4);
4724 : Real64 Xb;
4725 : Real64 Yb;
4726 : Real64 Perimeter;
4727 : int n;
4728 : int Vrt;
4729 :
4730 159 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone == 0 &&
4731 26 : (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Detached_F &&
4732 6 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Detached_B))
4733 0 : return;
4734 :
4735 139 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Height = Height;
4736 139 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Width = Length;
4737 :
4738 139 : SurfAzimuth = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth;
4739 139 : SurfTilt = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt;
4740 139 : CosSurfAzimuth = std::cos(SurfAzimuth * DataGlobalConstants::DegToRadians);
4741 139 : SinSurfAzimuth = std::sin(SurfAzimuth * DataGlobalConstants::DegToRadians);
4742 139 : CosSurfTilt = std::cos(SurfTilt * DataGlobalConstants::DegToRadians);
4743 139 : SinSurfTilt = std::sin(SurfTilt * DataGlobalConstants::DegToRadians);
4744 139 : if (!SurfWorldCoordSystem) {
4745 111 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone > 0) {
4746 285 : Xb = XCoord * state.dataSurfaceGeometry->CosZoneRelNorth(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone) -
4747 95 : YCoord * state.dataSurfaceGeometry->SinZoneRelNorth(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone) +
4748 95 : state.dataHeatBal->Zone(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone).OriginX;
4749 285 : Yb = XCoord * state.dataSurfaceGeometry->SinZoneRelNorth(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone) +
4750 95 : YCoord * state.dataSurfaceGeometry->CosZoneRelNorth(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone) +
4751 95 : state.dataHeatBal->Zone(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone).OriginY;
4752 95 : XLLC = Xb * state.dataSurfaceGeometry->CosBldgRelNorth - Yb * state.dataSurfaceGeometry->SinBldgRelNorth;
4753 95 : YLLC = Xb * state.dataSurfaceGeometry->SinBldgRelNorth + Yb * state.dataSurfaceGeometry->CosBldgRelNorth;
4754 95 : ZLLC = ZCoord + state.dataHeatBal->Zone(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone).OriginZ;
4755 : } else {
4756 16 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Detached_B) {
4757 5 : Xb = XCoord;
4758 5 : Yb = YCoord;
4759 5 : XLLC = Xb * state.dataSurfaceGeometry->CosBldgRelNorth - Yb * state.dataSurfaceGeometry->SinBldgRelNorth;
4760 5 : YLLC = Xb * state.dataSurfaceGeometry->SinBldgRelNorth + Yb * state.dataSurfaceGeometry->CosBldgRelNorth;
4761 5 : ZLLC = ZCoord;
4762 : } else {
4763 11 : XLLC = XCoord;
4764 11 : YLLC = YCoord;
4765 11 : ZLLC = ZCoord;
4766 : }
4767 : }
4768 : } else {
4769 : // for world coordinates, only rotate for appendix G
4770 28 : Xb = XCoord;
4771 28 : Yb = YCoord;
4772 28 : ZLLC = ZCoord;
4773 28 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Detached_F) {
4774 25 : XLLC = Xb * state.dataSurfaceGeometry->CosBldgRotAppGonly - Yb * state.dataSurfaceGeometry->SinBldgRotAppGonly;
4775 25 : YLLC = Xb * state.dataSurfaceGeometry->SinBldgRotAppGonly + Yb * state.dataSurfaceGeometry->CosBldgRotAppGonly;
4776 : } else {
4777 3 : XLLC = Xb;
4778 3 : YLLC = Yb;
4779 : }
4780 : }
4781 :
4782 139 : XX(1) = 0.0;
4783 139 : XX(2) = 0.0;
4784 139 : XX(3) = Length;
4785 139 : XX(4) = Length;
4786 139 : YY(1) = Height;
4787 139 : YY(4) = Height;
4788 139 : YY(3) = 0.0;
4789 139 : YY(2) = 0.0;
4790 :
4791 695 : for (n = 1; n <= state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides; ++n) {
4792 556 : Vrt = n;
4793 556 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(Vrt).x = XLLC - XX(n) * CosSurfAzimuth - YY(n) * CosSurfTilt * SinSurfAzimuth;
4794 556 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(Vrt).y = YLLC + XX(n) * SinSurfAzimuth - YY(n) * CosSurfTilt * CosSurfAzimuth;
4795 556 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(Vrt).z = ZLLC + YY(n) * SinSurfTilt;
4796 : }
4797 :
4798 278 : CreateNewellAreaVector(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
4799 139 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
4800 139 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellAreaVector);
4801 139 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea = VecLength(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellAreaVector);
4802 139 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea;
4803 139 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NetAreaShadowCalc = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area;
4804 278 : CreateNewellSurfaceNormalVector(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
4805 139 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
4806 139 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector);
4807 834 : DetermineAzimuthAndTilt(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
4808 139 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
4809 : SurfAzimuth,
4810 : SurfTilt,
4811 139 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsx,
4812 139 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsy,
4813 139 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsz,
4814 139 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea,
4815 139 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector);
4816 139 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth = SurfAzimuth;
4817 139 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt = SurfTilt;
4818 139 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConvOrientation =
4819 139 : ConvectionCoefficients::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
4820 : // Sine and cosine of azimuth and tilt
4821 139 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinAzim = SinSurfAzimuth;
4822 139 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosAzim = CosSurfAzimuth;
4823 139 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinTilt = SinSurfTilt;
4824 139 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt = CosSurfTilt;
4825 139 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGround = 0.5 * (1.0 - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt);
4826 : // Outward normal unit vector (pointing away from room)
4827 139 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector;
4828 556 : for (n = 1; n <= 3; ++n) {
4829 417 : if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) - 1.0) < 1.e-06)
4830 71 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) = +1.0;
4831 417 : if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) + 1.0) < 1.e-06)
4832 68 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) = -1.0;
4833 417 : if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n)) < 1.e-06)
4834 278 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) = 0.0;
4835 : }
4836 :
4837 : // Can perform tests on this surface here
4838 139 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSky = 0.5 * (1.0 + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt);
4839 : // The following IR view factors are modified in subr. SkyDifSolarShading if there are shadowing
4840 : // surfaces
4841 139 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSkyIR = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSky;
4842 139 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGroundIR = 0.5 * (1.0 - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt);
4843 :
4844 139 : Perimeter = distance(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides),
4845 139 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(1));
4846 556 : for (Vrt = 2; Vrt <= state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides; ++Vrt) {
4847 417 : Perimeter +=
4848 834 : distance(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(Vrt), state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(Vrt - 1));
4849 : }
4850 139 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Perimeter = Perimeter;
4851 :
4852 : // Call to transform vertices
4853 :
4854 139 : TransformVertsByAspect(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
4855 : }
4856 :
4857 771 : void GetHTSubSurfaceData(EnergyPlusData &state,
4858 : bool &ErrorsFound, // Error flag indicator (true if errors found)
4859 : int &SurfNum, // Count of Current SurfaceNumber
4860 : int const TotHTSubs, // Number of Heat Transfer SubSurfaces to obtain
4861 : const Array1D_string &SubSurfCls, // Valid Classes for Sub Surfaces
4862 : const Array1D<SurfaceClass> &SubSurfIDs, // ID Assignments for valid sub surface classes
4863 : int &AddedSubSurfaces, // Subsurfaces added when windows reference Window5
4864 : int &NeedToAddSurfaces // Number of surfaces to add, based on unentered IZ surfaces
4865 : )
4866 : {
4867 :
4868 : // SUBROUTINE INFORMATION:
4869 : // AUTHOR Linda Lawrie
4870 : // DATE WRITTEN May 2000
4871 : // MODIFIED August 2012 - line up subsurfaces with base surface types
4872 : // RE-ENGINEERED na
4873 :
4874 : // PURPOSE OF THIS SUBROUTINE:
4875 : // This subroutine gets the HeatTransfer Sub Surface Data,
4876 : // checks it for errors, etc.
4877 :
4878 : // METHODOLOGY EMPLOYED:
4879 : // na
4880 :
4881 : // REFERENCES:
4882 : // Heat Transfer Subsurface Definition
4883 : // FenestrationSurface:Detailed,
4884 : // \min-fields 19
4885 : // \memo Used for windows, doors, glass doors, tubular daylighting devices
4886 : // \format vertices
4887 : // A1 , \field Name
4888 : // \required-field
4889 : // \type alpha
4890 : // A2 , \field Surface Type
4891 : // \required-field
4892 : // \type choice
4893 : // \key Window
4894 : // \key Door
4895 : // \key GlassDoor
4896 : // \key TubularDaylightDome
4897 : // \key TubularDaylightDiffuser
4898 : // A3 , \field Construction Name
4899 : // \required-field
4900 : // \note To be matched with a construction in this input file
4901 : // \type object-list
4902 : // \object-list ConstructionNames
4903 : // A4 , \field Building Surface Name
4904 : // \required-field
4905 : // \type object-list
4906 : // \object-list SurfaceNames
4907 : // A5, \field Outside Boundary Condition Object
4908 : // \type object-list
4909 : // \object-list OutFaceEnvNames
4910 : // \note Non-blank only if base surface field Outside Boundary Condition is
4911 : // \note Surface or OtherSideCoefficients
4912 : // \note If Base Surface's Surface, specify name of corresponding subsurface in adjacent zone or
4913 : // \note specify current subsurface name for internal partition separating like zones
4914 : // \note If OtherSideCoefficients, specify name of SurfaceProperty:OtherSideCoefficients
4915 : // \note or leave blank to inherit Base Surface's OtherSide Coefficients
4916 : // N1, \field View Factor to Ground
4917 : // \type real
4918 : // \note From the exterior of the surface
4919 : // \note Unused if one uses the "reflections" options in Solar Distribution in Building input
4920 : // \note unless a DaylightingDevice:Shelf or DaylightingDevice:Tubular object has been specified.
4921 : // \note autocalculate will automatically calculate this value from the tilt of the surface
4922 : // \autocalculatable
4923 : // \minimum 0.0
4924 : // \maximum 1.0
4925 : // \default autocalculate
4926 : // A6, \field Frame and Divider Name
4927 : // \note Enter the name of a WindowProperty:FrameAndDivider object
4928 : // \type object-list
4929 : // \object-list WindowFrameAndDividerNames
4930 : // \note Used only for exterior windows (rectangular) and glass doors.
4931 : // \note Unused for triangular windows.
4932 : // \note If not specified (blank), window or glass door has no frame or divider
4933 : // \note and no beam solar reflection from reveal surfaces.
4934 : // N2 , \field Multiplier
4935 : // \note Used only for Surface Type = WINDOW, GLASSDOOR or DOOR
4936 : // \note Non-integer values will be truncated to integer
4937 : // \default 1.0
4938 : // \minimum 1.0
4939 : // N3 , \field Number of Vertices
4940 : // \minimum 3
4941 : // \maximum 4
4942 : // \autocalculatable
4943 : // \default autocalculate
4944 : // \note vertices are given in GlobalGeometryRules coordinates -- if relative, all surface coordinates
4945 : // \note are "relative" to the Zone Origin. If world, then building and zone origins are used
4946 : // \note for some internal calculations, but all coordinates are given in an "absolute" system.
4947 : // N4-15 as indicated by the N3 value
4948 :
4949 : // Using/Aliasing
4950 :
4951 : // Locals
4952 : // SUBROUTINE ARGUMENT DEFINITIONS:
4953 : // data file entry with two glazing systems
4954 :
4955 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
4956 : int IOStat; // IO Status when calling get input subroutine
4957 : int SurfaceNumAlpha; // Number of material alpha names being passed
4958 : int SurfaceNumProp; // Number of material properties being passed
4959 : int Found; // For matching interzone surfaces
4960 : int Loop;
4961 : int ValidChk;
4962 : int numSides;
4963 :
4964 771 : GetWindowShadingControlData(state, ErrorsFound);
4965 771 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
4966 771 : cCurrentModuleObject = "FenestrationSurface:Detailed";
4967 771 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, Loop, SurfaceNumAlpha, SurfaceNumProp);
4968 :
4969 771 : if (SurfaceNumAlpha != 6) {
4970 0 : ShowSevereError(
4971 0 : state, format("{}: Object Definition indicates not = 6 Alpha Objects, Number Indicated={}", cCurrentModuleObject, SurfaceNumAlpha));
4972 0 : ErrorsFound = true;
4973 : }
4974 :
4975 771 : if (SurfaceNumProp != 15) {
4976 0 : ShowSevereError(
4977 0 : state, format("{}: Object Definition indicates > 15 Numeric Objects, Number Indicated={}", cCurrentModuleObject, SurfaceNumAlpha));
4978 0 : ErrorsFound = true;
4979 : }
4980 771 : NeedToAddSurfaces = 0;
4981 :
4982 7144 : for (Loop = 1; Loop <= TotHTSubs; ++Loop) {
4983 44611 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
4984 : cCurrentModuleObject,
4985 : Loop,
4986 6373 : state.dataIPShortCut->cAlphaArgs,
4987 : SurfaceNumAlpha,
4988 6373 : state.dataIPShortCut->rNumericArgs,
4989 : SurfaceNumProp,
4990 : IOStat,
4991 6373 : state.dataIPShortCut->lNumericFieldBlanks,
4992 6373 : state.dataIPShortCut->lAlphaFieldBlanks,
4993 6373 : state.dataIPShortCut->cAlphaFieldNames,
4994 6373 : state.dataIPShortCut->cNumericFieldNames);
4995 :
4996 12746 : if (GlobalNames::VerifyUniqueInterObjectName(state,
4997 6373 : state.dataSurfaceGeometry->UniqueSurfaceNames,
4998 6373 : state.dataIPShortCut->cAlphaArgs(1),
4999 : cCurrentModuleObject,
5000 6373 : state.dataIPShortCut->cAlphaFieldNames(1),
5001 : ErrorsFound)) {
5002 0 : continue;
5003 : }
5004 :
5005 6373 : if (SurfaceNumProp < 12) {
5006 0 : ShowSevereError(state,
5007 0 : format("{}=\"{}\", Too few number of numeric args=[{}].",
5008 : cCurrentModuleObject,
5009 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
5010 0 : SurfaceNumProp));
5011 0 : ErrorsFound = true;
5012 : }
5013 :
5014 6373 : ++SurfNum;
5015 6373 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name = state.dataIPShortCut->cAlphaArgs(1); // Set the Surface Name in the Derived Type
5016 6373 : ValidChk = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(2), SubSurfCls, 6);
5017 6373 : if (ValidChk == 0) {
5018 0 : ShowSevereError(state,
5019 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
5020 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2));
5021 0 : ErrorsFound = true;
5022 : } else {
5023 6373 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SubSurfIDs(ValidChk); // Set class number
5024 : }
5025 :
5026 19119 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction = UtilityRoutines::FindItemInList(
5027 19119 : state.dataIPShortCut->cAlphaArgs(3), state.dataConstruction->Construct, state.dataHeatBal->TotConstructs);
5028 :
5029 6373 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction == 0) {
5030 0 : ShowSevereError(state,
5031 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
5032 0 : state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) + "\".");
5033 0 : ErrorsFound = true;
5034 0 : continue;
5035 : } else {
5036 6373 : state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).IsUsed = true;
5037 6373 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConstructionStoredInputValue =
5038 6373 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction;
5039 : }
5040 :
5041 13710 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Window ||
5042 1424 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::GlassDoor ||
5043 7291 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::TDD_Diffuser ||
5044 458 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::TDD_Dome) {
5045 :
5046 5917 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction != 0) {
5047 5917 : auto &construction = state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction);
5048 5917 : if (!construction.TypeIsWindow && !construction.TypeIsAirBoundary) {
5049 0 : ErrorsFound = true;
5050 0 : ShowSevereError(state,
5051 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
5052 : "\" has an opaque surface construction; it should have a window construction.");
5053 : }
5054 5917 : if (state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).SourceSinkPresent) {
5055 0 : ErrorsFound = true;
5056 0 : ShowSevereError(state,
5057 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
5058 : "\": Windows are not allowed to have embedded sources/sinks");
5059 : }
5060 : }
5061 :
5062 456 : } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction != 0) {
5063 456 : if (state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsWindow) {
5064 0 : ErrorsFound = true;
5065 0 : ShowSevereError(state,
5066 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
5067 0 : state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) +
5068 : "\" - has Window materials.");
5069 0 : ShowContinueError(state, "...because " + state.dataIPShortCut->cAlphaFieldNames(2) + '=' + state.dataIPShortCut->cAlphaArgs(2));
5070 : }
5071 : }
5072 :
5073 6373 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf = true;
5074 :
5075 6373 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName = state.dataIPShortCut->cAlphaArgs(4);
5076 : // The subsurface inherits properties from the base surface
5077 : // Exterior conditions, Zone, etc.
5078 : // We can figure out the base surface though, because they've all been entered
5079 19119 : Found = UtilityRoutines::FindItemInList(
5080 19119 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName, state.dataSurfaceGeometry->SurfaceTmp, state.dataSurface->TotSurfaces);
5081 6373 : if (Found > 0) {
5082 6373 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf = Found;
5083 6373 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCond;
5084 6373 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCondName;
5085 6373 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtSolar;
5086 6373 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtWind = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtWind;
5087 6373 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone = state.dataSurfaceGeometry->SurfaceTmp(Found).Zone;
5088 6373 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName = state.dataSurfaceGeometry->SurfaceTmp(Found).ZoneName;
5089 6373 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OSCPtr = state.dataSurfaceGeometry->SurfaceTmp(Found).OSCPtr;
5090 6437 : if (state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCond == UnreconciledZoneSurface &&
5091 64 : state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCondName ==
5092 64 : state.dataSurfaceGeometry->SurfaceTmp(Found).Name) { // Adiabatic surface, no windows or doors allowed
5093 0 : ShowSevereError(state,
5094 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
5095 0 : state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\".");
5096 0 : ShowContinueError(state, "... adiabatic surfaces cannot have windows or doors.");
5097 0 : ShowContinueError(state,
5098 : "... no solar transmission will result for these windows or doors. You must have interior windows or doors on "
5099 : "Interzone surfaces for transmission to result.");
5100 : }
5101 : } else {
5102 0 : ShowSevereError(state,
5103 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
5104 0 : state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataIPShortCut->cAlphaArgs(4));
5105 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName = "Unknown Zone";
5106 0 : ErrorsFound = true;
5107 : }
5108 12744 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::TDD_Dome ||
5109 6371 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::TDD_Diffuser) {
5110 4 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = ExternalEnvironment;
5111 : }
5112 :
5113 6373 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == ExternalEnvironment) {
5114 6294 : if (!state.dataIPShortCut->lAlphaFieldBlanks(5)) {
5115 0 : ShowWarningError(state,
5116 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid field " +
5117 0 : state.dataIPShortCut->cAlphaFieldNames(5));
5118 0 : ShowContinueError(state,
5119 0 : "...when Base surface uses \"Outdoors\" as " + state.dataIPShortCut->cAlphaFieldNames(5) +
5120 : ", subsurfaces need to be blank to inherit the outdoor characteristics.");
5121 0 : ShowContinueError(state, "...Surface external characteristics changed to reflect base surface.");
5122 : }
5123 : }
5124 :
5125 6373 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnreconciledZoneSurface) { // "Surface" Base Surface
5126 62 : if (!state.dataIPShortCut->lAlphaFieldBlanks(5)) {
5127 62 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataIPShortCut->cAlphaArgs(5);
5128 : } else {
5129 0 : ShowSevereError(state,
5130 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid blank " +
5131 0 : state.dataIPShortCut->cAlphaFieldNames(5));
5132 0 : ShowContinueError(state,
5133 0 : "...when Base surface uses \"Surface\" as " + state.dataIPShortCut->cAlphaFieldNames(5) +
5134 : ", subsurfaces must also specify specific surfaces in the adjacent zone.");
5135 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName =
5136 0 : state.dataIPShortCut->cAlphaArgs(5); // putting it as blank will not confuse things later.
5137 0 : ErrorsFound = true;
5138 : }
5139 : }
5140 :
5141 6373 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnenteredAdjacentZoneSurface) { // "Zone" - unmatched interior surface
5142 1 : ++NeedToAddSurfaces;
5143 : // ignoring window5datafiles for now -- will need to add.
5144 : }
5145 :
5146 12730 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == OtherSideCoefNoCalcExt ||
5147 6357 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == OtherSideCoefCalcExt) {
5148 16 : if (!state.dataIPShortCut->lAlphaFieldBlanks(5)) { // Otherside Coef special Name
5149 2 : Found = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(5), state.dataSurface->OSC, state.dataSurface->TotOSC);
5150 2 : if (Found == 0) {
5151 0 : ShowSevereError(state,
5152 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
5153 0 : state.dataIPShortCut->cAlphaFieldNames(5) + "=\"" + state.dataIPShortCut->cAlphaArgs(5) + "\".");
5154 0 : ShowContinueError(state, "...base surface requires that this subsurface have OtherSideCoefficients -- not found.");
5155 0 : ErrorsFound = true;
5156 : } else { // found
5157 : // The following allows for a subsurface that has different characteristics than
5158 : // the base surface with OtherSide Coeff -- do we want that or is it an error?
5159 2 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OSCPtr = Found;
5160 2 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataIPShortCut->cAlphaArgs(5);
5161 2 : if (state.dataSurface->OSC(Found).SurfFilmCoef > 0.0) {
5162 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = OtherSideCoefCalcExt;
5163 : } else {
5164 2 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = OtherSideCoefNoCalcExt;
5165 : }
5166 : }
5167 : }
5168 : }
5169 :
5170 6373 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == OtherSideCondModeledExt) {
5171 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = ExternalEnvironment;
5172 : }
5173 :
5174 6373 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName == BlankString) {
5175 6284 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
5176 : }
5177 6373 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGround = state.dataIPShortCut->rNumericArgs(1);
5178 6373 : if (state.dataIPShortCut->lNumericFieldBlanks(1))
5179 355 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGround = DataGlobalConstants::AutoCalculate;
5180 :
5181 6373 : if (state.dataIPShortCut->lNumericFieldBlanks(3) || state.dataIPShortCut->rNumericArgs(3) == DataGlobalConstants::AutoCalculate) {
5182 53 : state.dataIPShortCut->rNumericArgs(3) = (SurfaceNumProp - 3) / 3;
5183 53 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = state.dataIPShortCut->rNumericArgs(3);
5184 53 : if (mod(SurfaceNumProp - 3, 3) != 0) {
5185 0 : ShowWarningError(state,
5186 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", " +
5187 0 : format("{} not even multiple of 3. Will read in {}",
5188 0 : state.dataIPShortCut->cNumericFieldNames(3),
5189 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides));
5190 : }
5191 53 : if (state.dataIPShortCut->rNumericArgs(3) < 3) {
5192 0 : ShowSevereError(state,
5193 0 : format("{}=\"{}\", {} (autocalculate) must be >= 3. Only {} provided.",
5194 : cCurrentModuleObject,
5195 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
5196 0 : state.dataIPShortCut->cNumericFieldNames(3),
5197 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides));
5198 0 : ErrorsFound = true;
5199 0 : continue;
5200 : }
5201 : } else {
5202 6320 : numSides = (SurfaceNumProp - 2) / 3;
5203 6320 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = state.dataIPShortCut->rNumericArgs(3);
5204 6320 : if (numSides > state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides) {
5205 0 : ShowWarningError(state,
5206 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", field " +
5207 0 : state.dataIPShortCut->cNumericFieldNames(3) + '=' +
5208 0 : fmt::to_string(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides));
5209 0 : ShowContinueError(
5210 : state,
5211 0 : format("...but {} were entered. Only the indicated {} will be used.", numSides, state.dataIPShortCut->cNumericFieldNames(3)));
5212 : }
5213 : }
5214 6373 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.allocate(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
5215 13710 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Window ||
5216 6833 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::GlassDoor ||
5217 460 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Door)
5218 6369 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier = int(state.dataIPShortCut->rNumericArgs(2));
5219 : // Only windows, glass doors and doors can have Multiplier > 1:
5220 13710 : if ((state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Window &&
5221 1424 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::GlassDoor &&
5222 6837 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Door) &&
5223 4 : state.dataIPShortCut->rNumericArgs(2) > 1.0) {
5224 0 : ShowWarningError(state,
5225 0 : format("{}=\"{}\", invalid {}=[{:.1T}].",
5226 : cCurrentModuleObject,
5227 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
5228 0 : state.dataIPShortCut->cNumericFieldNames(2),
5229 0 : state.dataIPShortCut->rNumericArgs(2)));
5230 0 : ShowContinueError(state,
5231 0 : "...because " + state.dataIPShortCut->cAlphaFieldNames(2) + '=' + state.dataIPShortCut->cAlphaArgs(2) +
5232 : " multiplier will be set to 1.0.");
5233 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier = 1.0;
5234 : }
5235 :
5236 6373 : GetVertices(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides, state.dataIPShortCut->rNumericArgs({4, _}));
5237 :
5238 6373 : CheckConvexity(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
5239 6373 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).windowShadingControlList.clear();
5240 6373 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeWindowShadingControl = 0;
5241 6373 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HasShadeControl = false;
5242 :
5243 6373 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).shadedConstructionList.clear();
5244 6373 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeShadedConstruction = 0;
5245 6373 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).shadedStormWinConstructionList.clear();
5246 :
5247 13710 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Window ||
5248 1424 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::GlassDoor ||
5249 7291 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::TDD_Diffuser ||
5250 458 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::TDD_Dome) {
5251 :
5252 11834 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == OtherSideCoefNoCalcExt ||
5253 5917 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == OtherSideCoefCalcExt) {
5254 0 : ShowSevereError(state,
5255 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
5256 : "\", Other side coefficients are not allowed with windows.");
5257 0 : ErrorsFound = true;
5258 : }
5259 :
5260 5917 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == Ground) {
5261 0 : ShowSevereError(state,
5262 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
5263 : "\", Exterior boundary condition = Ground is not allowed with windows.");
5264 0 : ErrorsFound = true;
5265 : }
5266 :
5267 5917 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == KivaFoundation) {
5268 0 : ShowSevereError(state,
5269 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
5270 : "\", Exterior boundary condition = Foundation is not allowed with windows.");
5271 0 : ErrorsFound = true;
5272 : }
5273 :
5274 5917 : InitialAssociateWindowShadingControlFenestration(state, ErrorsFound, SurfNum);
5275 :
5276 5917 : CheckWindowShadingControlFrameDivider(state, "GetHTSubSurfaceData", ErrorsFound, SurfNum, 6);
5277 :
5278 5917 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides == 3) { // Triangular window
5279 2 : if (!state.dataIPShortCut->cAlphaArgs(6).empty()) {
5280 0 : ShowWarningError(state,
5281 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
5282 0 : state.dataIPShortCut->cAlphaFieldNames(6) + "=\"" + state.dataIPShortCut->cAlphaArgs(6) + "\".");
5283 0 : ShowContinueError(state, ".. because it is a triangular window and cannot have a frame or divider or reveal reflection.");
5284 0 : ShowContinueError(state, "Frame, divider and reveal reflection will be ignored for this window.");
5285 : }
5286 2 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider = 0;
5287 : } // End of check if window is triangular or rectangular
5288 :
5289 : } // check on non-opaquedoor subsurfaces
5290 :
5291 12746 : CheckSubSurfaceMiscellaneous(state,
5292 : "GetHTSubSurfaceData",
5293 : ErrorsFound,
5294 : SurfNum,
5295 6373 : state.dataIPShortCut->cAlphaArgs(1),
5296 6373 : state.dataIPShortCut->cAlphaArgs(3),
5297 6373 : AddedSubSurfaces);
5298 :
5299 : } // End of main loop over subsurfaces
5300 771 : }
5301 :
5302 771 : void GetRectSubSurfaces(EnergyPlusData &state,
5303 : bool &ErrorsFound, // Error flag indicator (true if errors found)
5304 : int &SurfNum, // Count of Current SurfaceNumber
5305 : int const TotWindows, // Number of Window SubSurfaces to obtain
5306 : int const TotDoors, // Number of Door SubSurfaces to obtain
5307 : int const TotGlazedDoors, // Number of Glass Door SubSurfaces to obtain
5308 : int const TotIZWindows, // Number of Interzone Window SubSurfaces to obtain
5309 : int const TotIZDoors, // Number of Interzone Door SubSurfaces to obtain
5310 : int const TotIZGlazedDoors, // Number of Interzone Glass Door SubSurfaces to obtain
5311 : const Array1D<SurfaceClass> &SubSurfIDs, // ID Assignments for valid sub surface classes
5312 : int &AddedSubSurfaces, // Subsurfaces added when windows reference Window5
5313 : int &NeedToAddSubSurfaces // Number of surfaces to add, based on unentered IZ surfaces
5314 : )
5315 : {
5316 :
5317 : // SUBROUTINE INFORMATION:
5318 : // AUTHOR Linda Lawrie
5319 : // DATE WRITTEN December 2008
5320 : // MODIFIED na
5321 : // RE-ENGINEERED na
5322 :
5323 : // PURPOSE OF THIS SUBROUTINE:
5324 : // Get simple (rectangular, relative origin to base surface) windows, doors, glazed doors.
5325 :
5326 : // Using/Aliasing
5327 :
5328 : // Locals
5329 : // SUBROUTINE ARGUMENT DEFINITIONS:
5330 : // data file entry with two glazing systems
5331 :
5332 : // SUBROUTINE PARAMETER DEFINITIONS:
5333 771 : static Array1D_string const cModuleObjects(6, {"Window", "Door", "GlazedDoor", "Window:Interzone", "Door:Interzone", "GlazedDoor:Interzone"});
5334 :
5335 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
5336 : int Item;
5337 : int ItemsToGet;
5338 : int Loop;
5339 : int NumAlphas;
5340 : int NumNumbers;
5341 : int IOStat; // IO Status when calling get input subroutine
5342 : int Found; // For matching base surfaces
5343 : bool GettingIZSurfaces;
5344 : int WindowShadingField;
5345 : int FrameField;
5346 : int OtherSurfaceField;
5347 : int ClassItem;
5348 : int IZFound;
5349 771 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
5350 5397 : for (Item = 1; Item <= 6; ++Item) {
5351 :
5352 4626 : cCurrentModuleObject = cModuleObjects(Item);
5353 4626 : if (Item == 1) {
5354 771 : ItemsToGet = TotWindows;
5355 771 : GettingIZSurfaces = false;
5356 771 : WindowShadingField = 4;
5357 771 : FrameField = 5;
5358 771 : OtherSurfaceField = 0;
5359 771 : ClassItem = 1;
5360 3855 : } else if (Item == 2) {
5361 771 : ItemsToGet = TotDoors;
5362 771 : GettingIZSurfaces = false;
5363 771 : WindowShadingField = 0;
5364 771 : FrameField = 0;
5365 771 : OtherSurfaceField = 0;
5366 771 : ClassItem = 2;
5367 3084 : } else if (Item == 3) {
5368 771 : ItemsToGet = TotGlazedDoors;
5369 771 : GettingIZSurfaces = false;
5370 771 : WindowShadingField = 4;
5371 771 : FrameField = 5;
5372 771 : OtherSurfaceField = 0;
5373 771 : ClassItem = 3;
5374 2313 : } else if (Item == 4) {
5375 771 : ItemsToGet = TotIZWindows;
5376 771 : GettingIZSurfaces = true;
5377 771 : WindowShadingField = 0;
5378 771 : FrameField = 0;
5379 771 : OtherSurfaceField = 4;
5380 771 : ClassItem = 1;
5381 1542 : } else if (Item == 5) {
5382 771 : ItemsToGet = TotIZDoors;
5383 771 : GettingIZSurfaces = true;
5384 771 : WindowShadingField = 0;
5385 771 : FrameField = 0;
5386 771 : OtherSurfaceField = 4;
5387 771 : ClassItem = 2;
5388 : } else { // Item = 6
5389 771 : ItemsToGet = TotIZGlazedDoors;
5390 771 : GettingIZSurfaces = true;
5391 771 : WindowShadingField = 0;
5392 771 : FrameField = 0;
5393 771 : OtherSurfaceField = 4;
5394 771 : ClassItem = 3;
5395 : }
5396 :
5397 4691 : for (Loop = 1; Loop <= ItemsToGet; ++Loop) {
5398 455 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
5399 : cCurrentModuleObject,
5400 : Loop,
5401 65 : state.dataIPShortCut->cAlphaArgs,
5402 : NumAlphas,
5403 65 : state.dataIPShortCut->rNumericArgs,
5404 : NumNumbers,
5405 : IOStat,
5406 65 : state.dataIPShortCut->lNumericFieldBlanks,
5407 65 : state.dataIPShortCut->lAlphaFieldBlanks,
5408 65 : state.dataIPShortCut->cAlphaFieldNames,
5409 65 : state.dataIPShortCut->cNumericFieldNames);
5410 :
5411 130 : if (GlobalNames::VerifyUniqueInterObjectName(state,
5412 65 : state.dataSurfaceGeometry->UniqueSurfaceNames,
5413 65 : state.dataIPShortCut->cAlphaArgs(1),
5414 : cCurrentModuleObject,
5415 65 : state.dataIPShortCut->cAlphaFieldNames(1),
5416 : ErrorsFound)) {
5417 0 : continue;
5418 : }
5419 :
5420 65 : if (NumNumbers < 5) {
5421 0 : ShowSevereError(state,
5422 0 : format("{}=\"{}\", Too few number of numeric args=[{}].",
5423 : cCurrentModuleObject,
5424 0 : state.dataIPShortCut->cAlphaArgs(1),
5425 0 : NumNumbers));
5426 0 : ErrorsFound = true;
5427 : }
5428 :
5429 65 : ++SurfNum;
5430 65 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name = state.dataIPShortCut->cAlphaArgs(1); // Set the Surface Name in the Derived Type
5431 65 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SubSurfIDs(ClassItem); // Set class number
5432 :
5433 195 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction = UtilityRoutines::FindItemInList(
5434 195 : state.dataIPShortCut->cAlphaArgs(2), state.dataConstruction->Construct, state.dataHeatBal->TotConstructs);
5435 :
5436 65 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction == 0) {
5437 0 : ErrorsFound = true;
5438 0 : ShowSevereError(state,
5439 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
5440 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) + "\".");
5441 : } else {
5442 65 : state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).IsUsed = true;
5443 65 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConstructionStoredInputValue =
5444 65 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction;
5445 : }
5446 :
5447 75 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Window ||
5448 10 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::GlassDoor) {
5449 :
5450 57 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction != 0) {
5451 57 : auto &construction = state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction);
5452 57 : if (!construction.TypeIsWindow && !construction.TypeIsAirBoundary) {
5453 0 : ErrorsFound = true;
5454 0 : ShowSevereError(state,
5455 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
5456 : "\" has an opaque surface construction; it should have a window construction.");
5457 : }
5458 57 : if (state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).SourceSinkPresent) {
5459 0 : ErrorsFound = true;
5460 0 : ShowSevereError(state,
5461 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
5462 : "\": Windows are not allowed to have embedded sources/sinks");
5463 : }
5464 : }
5465 :
5466 8 : } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction != 0) {
5467 8 : if (state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsWindow) {
5468 0 : ErrorsFound = true;
5469 0 : ShowSevereError(state,
5470 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
5471 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) +
5472 : "\" - has Window materials.");
5473 : }
5474 : }
5475 :
5476 65 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf = true;
5477 :
5478 65 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName = state.dataIPShortCut->cAlphaArgs(3);
5479 : // The subsurface inherits properties from the base surface
5480 : // Exterior conditions, Zone, etc.
5481 : // We can figure out the base surface though, because they've all been entered
5482 130 : Found = UtilityRoutines::FindItemInList(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName,
5483 65 : state.dataSurfaceGeometry->SurfaceTmp,
5484 65 : state.dataSurface->TotSurfaces);
5485 65 : if (Found > 0) {
5486 65 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf = Found;
5487 65 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCond;
5488 65 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCondName;
5489 65 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtSolar;
5490 65 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtWind = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtWind;
5491 65 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt = state.dataSurfaceGeometry->SurfaceTmp(Found).Tilt;
5492 65 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConvOrientation =
5493 65 : ConvectionCoefficients::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
5494 65 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth = state.dataSurfaceGeometry->SurfaceTmp(Found).Azimuth;
5495 65 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone = state.dataSurfaceGeometry->SurfaceTmp(Found).Zone;
5496 65 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName = state.dataSurfaceGeometry->SurfaceTmp(Found).ZoneName;
5497 65 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OSCPtr = state.dataSurfaceGeometry->SurfaceTmp(Found).OSCPtr;
5498 65 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGround = state.dataSurfaceGeometry->SurfaceTmp(Found).ViewFactorGround;
5499 65 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSky = state.dataSurfaceGeometry->SurfaceTmp(Found).ViewFactorSky;
5500 : } else {
5501 0 : ShowSevereError(state,
5502 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
5503 0 : state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3));
5504 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName = "Unknown Zone";
5505 0 : ErrorsFound = true;
5506 0 : continue;
5507 : }
5508 73 : if (state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCond == UnreconciledZoneSurface &&
5509 8 : state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCondName ==
5510 8 : state.dataSurfaceGeometry->SurfaceTmp(Found).Name) { // Adiabatic surface, no windows or doors allowed
5511 0 : ShowSevereError(state,
5512 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
5513 0 : state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) + "\".");
5514 0 : ShowContinueError(state, "... adiabatic surfaces cannot have windows or doors.");
5515 0 : ShowContinueError(state,
5516 : "... no solar transmission will result for these windows or doors. You must have interior windows or doors on "
5517 : "Interzone surfaces for transmission to result.");
5518 : }
5519 :
5520 65 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnreconciledZoneSurface) { // "Surface" Base Surface
5521 8 : if (!GettingIZSurfaces) {
5522 0 : ShowSevereError(
5523 0 : state, cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid use of object");
5524 0 : ShowContinueError(state,
5525 0 : "...when Base surface uses \"Surface\" as " + state.dataIPShortCut->cAlphaFieldNames(5) +
5526 : ", subsurfaces must also specify specific surfaces in the adjacent zone.");
5527 0 : ShowContinueError(state, "...Please use " + cCurrentModuleObject + ":Interzone to enter this surface.");
5528 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName =
5529 0 : BlankString; // putting it as blank will not confuse things later.
5530 0 : ErrorsFound = true;
5531 : }
5532 : }
5533 :
5534 65 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnreconciledZoneSurface) { // "Surface" Base Surface
5535 8 : if (GettingIZSurfaces) {
5536 8 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataIPShortCut->cAlphaArgs(OtherSurfaceField);
5537 24 : IZFound = UtilityRoutines::FindItemInList(
5538 24 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName, state.dataHeatBal->Zone, state.dataGlobal->NumOfZones);
5539 8 : if (IZFound > 0) state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = UnenteredAdjacentZoneSurface;
5540 : } else { // Interior Window
5541 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
5542 : }
5543 : }
5544 :
5545 : // This is the parent's property:
5546 65 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond ==
5547 : UnenteredAdjacentZoneSurface) { // OtherZone - unmatched interior surface
5548 3 : if (GettingIZSurfaces) {
5549 3 : ++NeedToAddSubSurfaces;
5550 : } else { // Interior Window
5551 0 : ShowSevereError(state,
5552 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
5553 0 : "\", invalid Interzone Surface, specify " + cCurrentModuleObject + ":InterZone");
5554 0 : ShowContinueError(state, "...when base surface is an interzone surface, subsurface must also be an interzone surface.");
5555 0 : ++NeedToAddSubSurfaces;
5556 0 : ErrorsFound = true;
5557 : }
5558 : }
5559 :
5560 65 : if (GettingIZSurfaces) {
5561 11 : if (state.dataIPShortCut->lAlphaFieldBlanks(OtherSurfaceField)) {
5562 : // blank -- set it up for unentered adjacent zone
5563 0 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond ==
5564 : UnenteredAdjacentZoneSurface) { // already set but need Zone
5565 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName =
5566 0 : state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCondName; // base surface has it
5567 0 : } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnreconciledZoneSurface) {
5568 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName =
5569 0 : state.dataSurfaceGeometry->SurfaceTmp(Found).ZoneName; // base surface has it
5570 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = UnenteredAdjacentZoneSurface;
5571 : } else { // not correct boundary condition for interzone subsurface
5572 0 : ShowSevereError(state,
5573 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
5574 : "\", invalid Base Surface type for Interzone Surface");
5575 0 : ShowContinueError(state,
5576 : "...when base surface is not an interzone surface, subsurface must also not be an interzone surface.");
5577 0 : ErrorsFound = true;
5578 : }
5579 : }
5580 : }
5581 :
5582 65 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == OtherSideCondModeledExt) {
5583 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = ExternalEnvironment;
5584 : }
5585 :
5586 : // SurfaceTmp(SurfNum)%ViewFactorGround = AutoCalculate
5587 :
5588 65 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = 4;
5589 65 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.allocate(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
5590 140 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Window ||
5591 73 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::GlassDoor ||
5592 8 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Door)
5593 65 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier = int(state.dataIPShortCut->rNumericArgs(1));
5594 : // Only windows, glass doors and doors can have Multiplier > 1:
5595 140 : if ((state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Window &&
5596 18 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::GlassDoor &&
5597 73 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Door) &&
5598 0 : state.dataIPShortCut->rNumericArgs(1) > 1.0) {
5599 0 : ShowWarningError(state,
5600 0 : format("{}=\"{}\", invalid {}=[{:.1T}].",
5601 : cCurrentModuleObject,
5602 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
5603 0 : state.dataIPShortCut->cNumericFieldNames(1),
5604 0 : state.dataIPShortCut->rNumericArgs(1)));
5605 0 : ShowContinueError(state,
5606 0 : "...because " + state.dataIPShortCut->cAlphaFieldNames(1) + '=' + state.dataIPShortCut->cAlphaArgs(1) +
5607 : " multiplier will be set to 1.0.");
5608 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier = 1.0;
5609 : }
5610 :
5611 325 : MakeRelativeRectangularVertices(state,
5612 65 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf,
5613 : SurfNum,
5614 65 : state.dataIPShortCut->rNumericArgs(2),
5615 65 : state.dataIPShortCut->rNumericArgs(3),
5616 65 : state.dataIPShortCut->rNumericArgs(4),
5617 65 : state.dataIPShortCut->rNumericArgs(5));
5618 :
5619 65 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area <= 0.0) {
5620 0 : ShowSevereError(state,
5621 0 : format("{}=\"{}\", Surface Area <= 0.0; Entered Area={:.2T}",
5622 : cCurrentModuleObject,
5623 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
5624 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area));
5625 0 : ErrorsFound = true;
5626 : }
5627 :
5628 65 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).windowShadingControlList.clear();
5629 65 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeWindowShadingControl = 0;
5630 65 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HasShadeControl = false;
5631 :
5632 65 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).shadedConstructionList.clear();
5633 65 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeShadedConstruction = 0;
5634 65 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).shadedStormWinConstructionList.clear();
5635 :
5636 65 : InitialAssociateWindowShadingControlFenestration(state, ErrorsFound, SurfNum);
5637 :
5638 73 : if (!GettingIZSurfaces && (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Window ||
5639 8 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::GlassDoor)) {
5640 :
5641 94 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == OtherSideCoefNoCalcExt ||
5642 47 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == OtherSideCoefCalcExt) {
5643 0 : ShowSevereError(state,
5644 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
5645 : "\", Other side coefficients are not allowed with windows.");
5646 0 : ErrorsFound = true;
5647 : }
5648 :
5649 47 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == Ground) {
5650 0 : ShowSevereError(state,
5651 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
5652 : "\", Exterior boundary condition = Ground is not allowed with windows.");
5653 0 : ErrorsFound = true;
5654 : }
5655 :
5656 47 : CheckWindowShadingControlFrameDivider(state, "GetRectSubSurfaces", ErrorsFound, SurfNum, FrameField);
5657 :
5658 : } // check on non-opaquedoor subsurfaces
5659 :
5660 130 : CheckSubSurfaceMiscellaneous(state,
5661 : "GetRectSubSurfaces",
5662 : ErrorsFound,
5663 : SurfNum,
5664 65 : state.dataIPShortCut->cAlphaArgs(1),
5665 65 : state.dataIPShortCut->cAlphaArgs(2),
5666 65 : AddedSubSurfaces);
5667 :
5668 : } // Getting Items
5669 : }
5670 771 : }
5671 :
5672 5964 : void CheckWindowShadingControlFrameDivider(EnergyPlusData &state,
5673 : std::string_view const cRoutineName, // routine name calling this one (for error messages)
5674 : bool &ErrorsFound, // true if errors have been found or are found here
5675 : int const SurfNum, // current surface number
5676 : int const FrameField // field number for frame/divider
5677 : )
5678 : {
5679 :
5680 : // SUBROUTINE INFORMATION:
5681 : // AUTHOR Linda Lawrie
5682 : // DATE WRITTEN December 2008
5683 : // MODIFIED na
5684 : // RE-ENGINEERED na
5685 :
5686 : // PURPOSE OF THIS SUBROUTINE:
5687 : // This routine performs checks on WindowShadingControl settings and Frame/Divider Settings.
5688 :
5689 : // Using/Aliasing
5690 :
5691 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
5692 : int ConstrNumSh; // Construction number with Shade
5693 : int ConstrNum; // Construction number
5694 : int ShDevNum; // Shading Device number
5695 : int Lay; // Layer number
5696 : int TotGlassLayers; // Number of glass layers in window construction
5697 : int TotLayers; // Number of layers in unshaded construction
5698 : int TotShLayers; // Number of layers in shaded construction
5699 : int MatGap; // Gap material number
5700 : int MatGap1; // Material number of gap to left (outer side) of between-glass shade/blind
5701 : int MatGap2; // Material number of gap to right (inner side) of between-glass shade/blind
5702 : int MatSh; // Between-glass shade/blind material number
5703 : Real64 MatGapCalc; // Calculated MatGap diff for shaded vs non-shaded constructions
5704 :
5705 : // If WindowShadingControl has been specified for this window --
5706 : // Set shaded construction number if shaded construction was specified in WindowShadingControl.
5707 : // Otherwise, create shaded construction if WindowShadingControl for this window has
5708 : // interior or exterior shade/blind (but not between-glass shade/blind) specified.
5709 :
5710 6111 : for (std::size_t shadeControlIndex = 0; shadeControlIndex < state.dataSurfaceGeometry->SurfaceTmp(SurfNum).windowShadingControlList.size();
5711 : ++shadeControlIndex) {
5712 147 : int WSCPtr = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).windowShadingControlList[shadeControlIndex];
5713 147 : ConstrNumSh = 0;
5714 147 : if (!ErrorsFound && state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HasShadeControl) {
5715 147 : ConstrNumSh = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).shadedConstructionList[shadeControlIndex];
5716 147 : if (ConstrNumSh > 0) {
5717 129 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeShadedConstruction = ConstrNumSh;
5718 : } else {
5719 18 : if (ANY_INTERIOR_SHADE_BLIND(state.dataSurface->WindowShadingControl(WSCPtr).ShadingType) ||
5720 0 : ANY_EXTERIOR_SHADE_BLIND_SCREEN(state.dataSurface->WindowShadingControl(WSCPtr).ShadingType)) {
5721 18 : ShDevNum = state.dataSurface->WindowShadingControl(WSCPtr).ShadingDevice;
5722 18 : if (ShDevNum > 0) {
5723 18 : CreateShadedWindowConstruction(state, SurfNum, WSCPtr, ShDevNum, shadeControlIndex);
5724 18 : ConstrNumSh = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeShadedConstruction;
5725 : }
5726 : }
5727 : }
5728 : }
5729 :
5730 : // Error checks for shades and blinds
5731 :
5732 147 : ConstrNum = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction;
5733 147 : if (!ErrorsFound && WSCPtr > 0 && ConstrNum > 0 && ConstrNumSh > 0) {
5734 :
5735 147 : if (ANY_INTERIOR_SHADE_BLIND(state.dataSurface->WindowShadingControl(WSCPtr).ShadingType)) {
5736 80 : TotLayers = state.dataConstruction->Construct(ConstrNum).TotLayers;
5737 80 : TotShLayers = state.dataConstruction->Construct(ConstrNumSh).TotLayers;
5738 80 : if (TotShLayers - 1 != TotLayers) {
5739 0 : ShowWarningError(
5740 : state,
5741 : "WindowShadingControl: Interior shade or blind: Potential problem in match of unshaded/shaded constructions, "
5742 : "shaded should have 1 more layers than unshaded.");
5743 0 : ShowContinueError(state, "Unshaded construction=" + state.dataConstruction->Construct(ConstrNum).Name);
5744 0 : ShowContinueError(state, "Shaded construction=" + state.dataConstruction->Construct(ConstrNumSh).Name);
5745 0 : ShowContinueError(state,
5746 : "If preceding two constructions are same name, you have likely specified a WindowShadingControl (Field #3) "
5747 : "with the Window Construction rather than a shaded construction.");
5748 : }
5749 232 : for (Lay = 1; Lay <= state.dataConstruction->Construct(ConstrNum).TotLayers; ++Lay) {
5750 304 : if (state.dataConstruction->Construct(ConstrNum).LayerPoint(Lay) !=
5751 152 : state.dataConstruction->Construct(ConstrNumSh).LayerPoint(Lay)) {
5752 0 : ErrorsFound = true;
5753 0 : ShowSevereError(state,
5754 0 : " The glass and gas layers in the shaded and unshaded constructions do not match for window=" +
5755 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name);
5756 0 : ShowContinueError(state, "Unshaded construction=" + state.dataConstruction->Construct(ConstrNum).Name);
5757 0 : ShowContinueError(state, "Shaded construction=" + state.dataConstruction->Construct(ConstrNumSh).Name);
5758 0 : break;
5759 : }
5760 : }
5761 : }
5762 :
5763 147 : if (ANY_EXTERIOR_SHADE_BLIND_SCREEN(state.dataSurface->WindowShadingControl(WSCPtr).ShadingType)) {
5764 28 : TotLayers = state.dataConstruction->Construct(ConstrNum).TotLayers;
5765 28 : TotShLayers = state.dataConstruction->Construct(ConstrNumSh).TotLayers;
5766 28 : if (TotShLayers - 1 != TotLayers) {
5767 0 : ShowWarningError(state,
5768 : "WindowShadingControl: Exterior shade, screen or blind: Potential problem in match of unshaded/shaded "
5769 : "constructions, shaded should have 1 more layer than unshaded.");
5770 0 : ShowContinueError(state, "Unshaded construction=" + state.dataConstruction->Construct(ConstrNum).Name);
5771 0 : ShowContinueError(state, "Shaded construction=" + state.dataConstruction->Construct(ConstrNumSh).Name);
5772 0 : ShowContinueError(
5773 : state,
5774 : "If preceding two constructions have the same name, you have likely specified a WindowShadingControl (Field "
5775 : "#3) with the Window Construction rather than a shaded construction.");
5776 : }
5777 76 : for (Lay = 1; Lay <= state.dataConstruction->Construct(ConstrNum).TotLayers; ++Lay) {
5778 96 : if (state.dataConstruction->Construct(ConstrNum).LayerPoint(Lay) !=
5779 48 : state.dataConstruction->Construct(ConstrNumSh).LayerPoint(Lay + 1)) {
5780 0 : ErrorsFound = true;
5781 0 : ShowSevereError(state,
5782 0 : " The glass and gas layers in the shaded and unshaded constructions do not match for window=" +
5783 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name);
5784 0 : ShowContinueError(state, "Unshaded construction=" + state.dataConstruction->Construct(ConstrNum).Name);
5785 0 : ShowContinueError(state, "Shaded construction=" + state.dataConstruction->Construct(ConstrNumSh).Name);
5786 0 : break;
5787 : }
5788 : }
5789 : }
5790 :
5791 147 : if (ANY_BETWEENGLASS_SHADE_BLIND(state.dataSurface->WindowShadingControl(WSCPtr).ShadingType)) {
5792 : // Divider not allowed with between-glass shade or blind
5793 9 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider > 0) {
5794 0 : if (state.dataSurface->FrameDivider(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider).DividerWidth > 0.0) {
5795 0 : ShowWarningError(state,
5796 0 : "A divider cannot be specified for window " + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name);
5797 0 : ShowContinueError(state, ", which has a between-glass shade or blind.");
5798 0 : ShowContinueError(state, "Calculation will proceed without the divider for this window.");
5799 0 : state.dataSurface->FrameDivider(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider).DividerWidth = 0.0;
5800 : }
5801 : }
5802 : // Check consistency of gap widths between unshaded and shaded constructions
5803 9 : TotGlassLayers = state.dataConstruction->Construct(ConstrNum).TotGlassLayers;
5804 9 : TotLayers = state.dataConstruction->Construct(ConstrNum).TotLayers;
5805 9 : TotShLayers = state.dataConstruction->Construct(ConstrNumSh).TotLayers;
5806 9 : if (TotShLayers - 2 != TotLayers) {
5807 0 : ShowWarningError(
5808 : state,
5809 : "WindowShadingControl: Between Glass Shade/Blind: Potential problem in match of unshaded/shaded constructions, "
5810 : "shaded should have 2 more layers than unshaded.");
5811 0 : ShowContinueError(state, "Unshaded construction=" + state.dataConstruction->Construct(ConstrNum).Name);
5812 0 : ShowContinueError(state, "Shaded construction=" + state.dataConstruction->Construct(ConstrNumSh).Name);
5813 0 : ShowContinueError(state,
5814 : "If preceding two constructions are same name, you have likely specified a WindowShadingControl (Field #3) "
5815 : "with the Window Construction rather than a shaded construction.");
5816 : }
5817 18 : if (state.dataConstruction->Construct(ConstrNum).LayerPoint(TotLayers) !=
5818 9 : state.dataConstruction->Construct(ConstrNumSh).LayerPoint(TotShLayers)) {
5819 0 : ShowSevereError(state,
5820 0 : std::string{cRoutineName} + ": Mis-match in unshaded/shaded inside layer materials. These should match.");
5821 0 : ShowContinueError(state,
5822 0 : "Unshaded construction=" + state.dataConstruction->Construct(ConstrNum).Name + ", Material=" +
5823 0 : state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNum).LayerPoint(TotLayers)).Name);
5824 0 : ShowContinueError(
5825 : state,
5826 0 : "Shaded construction=" + state.dataConstruction->Construct(ConstrNumSh).Name + ", Material=" +
5827 0 : state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNumSh).LayerPoint(TotShLayers)).Name);
5828 0 : ErrorsFound = true;
5829 : }
5830 9 : if (state.dataConstruction->Construct(ConstrNum).LayerPoint(1) != state.dataConstruction->Construct(ConstrNumSh).LayerPoint(1)) {
5831 0 : ShowSevereError(state,
5832 0 : std::string{cRoutineName} + ": Mis-match in unshaded/shaded inside layer materials. These should match.");
5833 0 : ShowContinueError(state,
5834 0 : "Unshaded construction=" + state.dataConstruction->Construct(ConstrNum).Name + ", Material=" +
5835 0 : state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNum).LayerPoint(1)).Name);
5836 0 : ShowContinueError(state,
5837 0 : "Shaded construction=" + state.dataConstruction->Construct(ConstrNumSh).Name + ", Material=" +
5838 0 : state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNumSh).LayerPoint(1)).Name);
5839 0 : ErrorsFound = true;
5840 : }
5841 9 : if (TotGlassLayers == 2 || TotGlassLayers == 3) {
5842 9 : MatGap = state.dataConstruction->Construct(ConstrNum).LayerPoint(2 * TotGlassLayers - 2);
5843 9 : MatGap1 = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(2 * TotGlassLayers - 2);
5844 9 : MatGap2 = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(2 * TotGlassLayers);
5845 9 : MatSh = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(2 * TotGlassLayers - 1);
5846 9 : if (state.dataSurface->WindowShadingControl(WSCPtr).ShadingType == WinShadingType::BGBlind) {
5847 10 : MatGapCalc = std::abs(state.dataMaterial->Material(MatGap).Thickness - (state.dataMaterial->Material(MatGap1).Thickness +
5848 5 : state.dataMaterial->Material(MatGap2).Thickness));
5849 5 : if (MatGapCalc > 0.001) {
5850 0 : ShowSevereError(state,
5851 0 : std::string{cRoutineName} + ": The gap width(s) for the unshaded window construction " +
5852 0 : state.dataConstruction->Construct(ConstrNum).Name);
5853 0 : ShowContinueError(state,
5854 0 : "are inconsistent with the gap widths for shaded window construction " +
5855 0 : state.dataConstruction->Construct(ConstrNumSh).Name);
5856 0 : ShowContinueError(state,
5857 0 : "for window " + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
5858 : ", which has a between-glass blind.");
5859 0 : ShowContinueError(state,
5860 0 : format("..Material={} thickness={:.3R} -",
5861 0 : state.dataMaterial->Material(MatGap).Name,
5862 0 : state.dataMaterial->Material(MatGap).Thickness));
5863 0 : ShowContinueError(state,
5864 0 : format("..( Material={} thickness={:.3R} +",
5865 0 : state.dataMaterial->Material(MatGap1).Name,
5866 0 : state.dataMaterial->Material(MatGap1).Thickness));
5867 0 : ShowContinueError(state,
5868 0 : format("..Material={} thickness={:.3R} )=[{:.3R}] >.001",
5869 0 : state.dataMaterial->Material(MatGap2).Name,
5870 0 : state.dataMaterial->Material(MatGap2).Thickness,
5871 0 : MatGapCalc));
5872 0 : ErrorsFound = true;
5873 : }
5874 : } else { // Between-glass shade
5875 8 : MatGapCalc = std::abs(state.dataMaterial->Material(MatGap).Thickness -
5876 8 : (state.dataMaterial->Material(MatGap1).Thickness + state.dataMaterial->Material(MatGap2).Thickness +
5877 4 : state.dataMaterial->Material(MatSh).Thickness));
5878 4 : if (MatGapCalc > 0.001) {
5879 0 : ShowSevereError(state,
5880 0 : std::string{cRoutineName} + ": The gap width(s) for the unshaded window construction " +
5881 0 : state.dataConstruction->Construct(ConstrNum).Name);
5882 0 : ShowContinueError(state,
5883 0 : "are inconsistent with the gap widths for shaded window construction " +
5884 0 : state.dataConstruction->Construct(ConstrNumSh).Name);
5885 0 : ShowContinueError(state,
5886 0 : "for window " + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
5887 : ", which has a between-glass shade.");
5888 0 : ShowContinueError(state,
5889 0 : format("..Material={} thickness={:.3R} -",
5890 0 : state.dataMaterial->Material(MatGap).Name,
5891 0 : state.dataMaterial->Material(MatGap).Thickness));
5892 0 : ShowContinueError(state,
5893 0 : format("...( Material={} thickness={:.3R} +",
5894 0 : state.dataMaterial->Material(MatGap1).Name,
5895 0 : state.dataMaterial->Material(MatGap1).Thickness));
5896 0 : ShowContinueError(state,
5897 0 : format("..Material={} thickness={:.3R} +",
5898 0 : state.dataMaterial->Material(MatGap2).Name,
5899 0 : state.dataMaterial->Material(MatGap2).Thickness));
5900 0 : ShowContinueError(state,
5901 0 : format("..Material={} thickness={:.3R} )=[{:.3R}] >.001",
5902 0 : state.dataMaterial->Material(MatSh).Name,
5903 0 : state.dataMaterial->Material(MatSh).Thickness,
5904 0 : MatGapCalc));
5905 0 : ErrorsFound = true;
5906 : }
5907 : }
5908 : }
5909 : }
5910 : }
5911 : }
5912 5964 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
5913 5964 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides != 3) { // Rectangular Window
5914 : // Initialize the FrameDivider number for this window. W5FrameDivider will be positive if
5915 : // this window's construction came from the Window5 data file and that construction had an
5916 : // associated frame or divider. It will be zero if the window's construction is not from the
5917 : // Window5 data file, or the construction is from the data file, but the construction has no
5918 : // associated frame or divider. Note that if there is a FrameDivider candidate for this
5919 : // window from the Window5 data file it is used instead of the window's input FrameDivider.
5920 :
5921 5962 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction != 0) {
5922 5962 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider =
5923 5962 : state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).W5FrameDivider;
5924 :
5925 : // Warning if FrameAndDivider for this window is over-ridden by one from Window5 Data File
5926 5962 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider > 0 && !state.dataIPShortCut->lAlphaFieldBlanks(FrameField)) {
5927 0 : ShowSevereError(state,
5928 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", " +
5929 0 : state.dataIPShortCut->cAlphaFieldNames(FrameField) + "=\"" + state.dataIPShortCut->cAlphaArgs(FrameField) +
5930 : "\"");
5931 0 : ShowContinueError(state,
5932 0 : "will be replaced with FrameAndDivider from Window5 Data File entry " +
5933 0 : state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).Name);
5934 : }
5935 :
5936 5962 : if (!state.dataIPShortCut->lAlphaFieldBlanks(FrameField) && state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider == 0) {
5937 373 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider =
5938 373 : UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(FrameField), state.dataSurface->FrameDivider);
5939 373 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider == 0) {
5940 0 : if (!state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).WindowTypeEQL) {
5941 0 : ShowSevereError(state,
5942 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
5943 0 : state.dataIPShortCut->cAlphaFieldNames(FrameField) + "=\"" +
5944 0 : state.dataIPShortCut->cAlphaArgs(FrameField) + "\"");
5945 0 : ErrorsFound = true;
5946 : } else {
5947 0 : ShowSevereError(state,
5948 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
5949 0 : state.dataIPShortCut->cAlphaFieldNames(FrameField) + "=\"" +
5950 0 : state.dataIPShortCut->cAlphaArgs(FrameField) + "\"");
5951 0 : ShowContinueError(state, "...Frame/Divider is not supported in Equivalent Layer Window model.");
5952 : }
5953 : }
5954 : // Divider not allowed with between-glass shade or blind
5955 414 : for (int WSCPtr : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).windowShadingControlList) {
5956 41 : if (!ErrorsFound && WSCPtr > 0 && ConstrNumSh > 0) {
5957 41 : if (ANY_BETWEENGLASS_SHADE_BLIND(state.dataSurface->WindowShadingControl(WSCPtr).ShadingType)) {
5958 1 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider > 0) {
5959 1 : if (state.dataSurface->FrameDivider(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider).DividerWidth >
5960 : 0.0) {
5961 0 : ShowSevereError(state,
5962 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
5963 0 : "\", invalid " + state.dataIPShortCut->cAlphaFieldNames(FrameField) + "=\"" +
5964 0 : state.dataIPShortCut->cAlphaArgs(FrameField) + "\"");
5965 0 : ShowContinueError(state,
5966 : "Divider cannot be specified because the construction has a between-glass shade or blind.");
5967 0 : ShowContinueError(state, "Calculation will proceed without the divider for this window.");
5968 0 : ShowContinueError(
5969 : state,
5970 0 : format("Divider width = [{:.2R}].",
5971 0 : state.dataSurface->FrameDivider(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider)
5972 0 : .DividerWidth));
5973 0 : state.dataSurface->FrameDivider(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider).DividerWidth =
5974 : 0.0;
5975 : }
5976 : } // End of check if window has divider
5977 : } // End of check if window has a between-glass shade or blind
5978 : } // End of check if window has a shaded construction
5979 : } // end of looping through window shading controls of window
5980 : } // End of check if window has an associated FrameAndDivider
5981 : } // End of check if window has a construction
5982 : }
5983 :
5984 5964 : if (state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).WindowTypeEQL) {
5985 3 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider > 0) {
5986 : // Equivalent Layer window does not have frame/divider model
5987 0 : ShowSevereError(state,
5988 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
5989 0 : state.dataIPShortCut->cAlphaFieldNames(FrameField) + "=\"" + state.dataIPShortCut->cAlphaArgs(FrameField) + "\"");
5990 0 : ShowContinueError(state, "Frame/Divider is not supported in Equivalent Layer Window model.");
5991 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider = 0;
5992 : }
5993 : }
5994 5964 : }
5995 :
5996 6438 : void CheckSubSurfaceMiscellaneous(EnergyPlusData &state,
5997 : std::string_view const cRoutineName, // routine name calling this one (for error messages)
5998 : bool &ErrorsFound, // true if errors have been found or are found here
5999 : int const SurfNum, // current surface number
6000 : std::string const &SubSurfaceName, // name of the surface
6001 : std::string const &SubSurfaceConstruction, // name of the construction
6002 : int &AddedSubSurfaces)
6003 : {
6004 :
6005 : // SUBROUTINE INFORMATION:
6006 : // AUTHOR Linda Lawrie
6007 : // DATE WRITTEN December 2008
6008 : // MODIFIED na
6009 : // RE-ENGINEERED na
6010 :
6011 : // PURPOSE OF THIS SUBROUTINE:
6012 : // This routine performs miscellaneous checks on subsurfaces: Windows, GlassDoors, Doors, Tubular Devices.
6013 :
6014 : // Using/Aliasing
6015 :
6016 : using namespace DataErrorTracking;
6017 :
6018 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
6019 : int NumShades; // count on number of shading layers
6020 : int Lay; // Layer number
6021 : int LayerPtr; // Layer pointer
6022 : int ConstrNum; // Construction number
6023 : int Found; // when item is found
6024 :
6025 : // Warning if window has multiplier > 1 and SolarDistribution = FullExterior or FullInteriorExterior
6026 :
6027 13850 : if ((state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Window ||
6028 6944 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::GlassDoor) &&
6029 17579 : static_cast<int>(state.dataHeatBal->SolarDistribution) > static_cast<int>(DataHeatBalance::Shadowing::Minimal) &&
6030 5171 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier > 1.0) {
6031 6 : if (state.dataGlobal->DisplayExtraWarnings) {
6032 0 : ShowWarningError(state,
6033 0 : std::string{cRoutineName} + ": A Multiplier > 1.0 for window/glass door " +
6034 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name);
6035 0 : ShowContinueError(state, "in conjunction with SolarDistribution = FullExterior or FullInteriorExterior");
6036 0 : ShowContinueError(state, "can cause inaccurate shadowing on the window and/or");
6037 0 : ShowContinueError(state, "inaccurate interior solar distribution from the window.");
6038 : }
6039 6 : ++state.dataErrTracking->TotalMultipliedWindows;
6040 : }
6041 :
6042 : // Require that a construction referenced by a surface that is a window
6043 : // NOT have a shading device layer; use WindowShadingControl to specify a shading device.
6044 6438 : ConstrNum = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction;
6045 6438 : if (ConstrNum > 0) {
6046 6438 : NumShades = 0;
6047 16990 : for (Lay = 1; Lay <= state.dataConstruction->Construct(ConstrNum).TotLayers; ++Lay) {
6048 10552 : LayerPtr = state.dataConstruction->Construct(ConstrNum).LayerPoint(Lay);
6049 10552 : if (LayerPtr == 0) continue; // Error is caught already, will terminate later
6050 31656 : if (state.dataMaterial->Material(LayerPtr).Group == DataHeatBalance::MaterialGroup::Shade ||
6051 21104 : state.dataMaterial->Material(LayerPtr).Group == DataHeatBalance::MaterialGroup::WindowBlind ||
6052 10552 : state.dataMaterial->Material(LayerPtr).Group == DataHeatBalance::MaterialGroup::Screen)
6053 0 : ++NumShades;
6054 : }
6055 6438 : if (NumShades != 0) {
6056 0 : ShowSevereError(state, std::string{cRoutineName} + ": Window \"" + SubSurfaceName + "\" must not directly reference");
6057 0 : ShowContinueError(state, "a Construction (i.e, \"" + SubSurfaceConstruction + "\") with a shading device.");
6058 0 : ShowContinueError(state, "Use WindowShadingControl to specify a shading device for a window.");
6059 0 : ErrorsFound = true;
6060 : }
6061 : }
6062 :
6063 : // Disallow glass transmittance dirt factor for interior windows and glass doors
6064 :
6065 6541 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond != ExternalEnvironment &&
6066 171 : (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Window ||
6067 80 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::GlassDoor)) {
6068 12 : ConstrNum = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction;
6069 12 : if (ConstrNum > 0) {
6070 24 : for (Lay = 1; Lay <= state.dataConstruction->Construct(ConstrNum).TotLayers; ++Lay) {
6071 12 : LayerPtr = state.dataConstruction->Construct(ConstrNum).LayerPoint(Lay);
6072 24 : if (state.dataMaterial->Material(LayerPtr).Group == DataHeatBalance::MaterialGroup::WindowGlass &&
6073 12 : state.dataMaterial->Material(LayerPtr).GlassTransDirtFactor < 1.0) {
6074 0 : ShowSevereError(state,
6075 0 : std::string{cRoutineName} + ": Interior Window or GlassDoor " + SubSurfaceName + " has a glass layer with");
6076 0 : ShowContinueError(state, "Dirt Correction Factor for Solar and Visible Transmittance < 1.0");
6077 0 : ShowContinueError(state, "A value less than 1.0 for this factor is only allowed for exterior windows and glass doors.");
6078 0 : ErrorsFound = true;
6079 : }
6080 : }
6081 : }
6082 : }
6083 :
6084 : // If this is a window with a construction from the Window5DataFile, call routine that will
6085 : // (1) if one glazing system on Data File, give warning message if window height or width
6086 : // differ by more than 10% from those of the glazing system on the Data File;
6087 : // (2) if two glazing systems (separated by a mullion) on Data File, create a second window
6088 : // and adjust the dimensions of the original and second windows to those on the Data File
6089 :
6090 6438 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction != 0) {
6091 :
6092 6438 : if (state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).FromWindow5DataFile) {
6093 :
6094 8 : ModifyWindow(state, SurfNum, ErrorsFound, AddedSubSurfaces);
6095 :
6096 : } else {
6097 : // Calculate net area for base surface (note that ModifyWindow, above, adjusts net area of
6098 : // base surface for case where window construction is from Window5 Data File
6099 : // In case there is in error in this window's base surface (i.e. none)..
6100 6430 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf > 0) {
6101 6430 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).Area -=
6102 6430 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area;
6103 :
6104 : // Subtract TDD:DIFFUSER area from other side interzone surface
6105 6432 : if ((state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::TDD_Diffuser) &&
6106 2 : not_blank(state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf)
6107 : .ExtBoundCondName)) { // Base surface is an interzone surface
6108 : // Lookup interzone surface of the base surface
6109 : // (Interzone surfaces have not been assigned yet, but all base surfaces should already be loaded.)
6110 4 : Found = UtilityRoutines::FindItemInList(
6111 2 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).ExtBoundCondName,
6112 2 : state.dataSurfaceGeometry->SurfaceTmp,
6113 : SurfNum);
6114 2 : if (Found != 0) state.dataSurfaceGeometry->SurfaceTmp(Found).Area -= state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area;
6115 : }
6116 6430 : if (state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).Area <= 0.0) {
6117 0 : ShowSevereError(state,
6118 0 : std::string{cRoutineName} + ": Surface Openings have too much area for base surface=" +
6119 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).Name);
6120 0 : ShowContinueError(state, "Opening Surface creating error=" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name);
6121 0 : ErrorsFound = true;
6122 : }
6123 : // Net area of base surface with unity window multipliers (used in shadowing checks)
6124 : // For Windows, Glass Doors and Doors, just one area is subtracted. For the rest, should be
6125 : // full area.
6126 7404 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Window ||
6127 974 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::GlassDoor) {
6128 5962 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).NetAreaShadowCalc -=
6129 5962 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area / state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier;
6130 468 : } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Door) { // Door, TDD:Diffuser, TDD:DOME
6131 464 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).NetAreaShadowCalc -=
6132 464 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area / state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier;
6133 : } else {
6134 4 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).NetAreaShadowCalc -=
6135 4 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area;
6136 : }
6137 : }
6138 : }
6139 : }
6140 6438 : }
6141 :
6142 107 : void MakeRelativeRectangularVertices(EnergyPlusData &state,
6143 : int const BaseSurfNum, // Base surface
6144 : int const SurfNum,
6145 : Real64 const XCoord,
6146 : Real64 const ZCoord,
6147 : Real64 const Length,
6148 : Real64 const Height)
6149 : {
6150 :
6151 : // SUBROUTINE INFORMATION:
6152 : // AUTHOR Linda Lawrie
6153 : // DATE WRITTEN December 2008
6154 : // MODIFIED na
6155 : // RE-ENGINEERED na
6156 :
6157 : // PURPOSE OF THIS SUBROUTINE:
6158 : // This routine creates world/3d coordinates for rectangular surfaces using relative X and Z, length & height.
6159 :
6160 : // METHODOLOGY EMPLOYED:
6161 : // na
6162 :
6163 : // REFERENCES:
6164 : // na
6165 :
6166 : // Using/Aliasing
6167 : using namespace Vectors;
6168 :
6169 : // Locals
6170 : // SUBROUTINE ARGUMENT DEFINITIONS:
6171 :
6172 : // SUBROUTINE PARAMETER DEFINITIONS:
6173 : // na
6174 :
6175 : // INTERFACE BLOCK SPECIFICATIONS:
6176 : // na
6177 :
6178 : // DERIVED TYPE DEFINITIONS:
6179 : // na
6180 :
6181 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
6182 : Real64 SurfAzimuth; // Surface Azimuth/Facing (same as Base Surface)
6183 : Real64 SurfTilt; // Tilt (same as Base Surface)
6184 : Real64 XLLC;
6185 : Real64 YLLC;
6186 : Real64 ZLLC;
6187 : Real64 CosSurfAzimuth;
6188 : Real64 SinSurfAzimuth;
6189 : Real64 CosSurfTilt;
6190 : Real64 SinSurfTilt;
6191 : Real64 BaseCosSurfAzimuth;
6192 : Real64 BaseSinSurfAzimuth;
6193 : Real64 BaseCosSurfTilt;
6194 : Real64 BaseSinSurfTilt;
6195 214 : Array1D<Real64> XX(4);
6196 214 : Array1D<Real64> YY(4);
6197 : Real64 Perimeter;
6198 : int n;
6199 : int Vrt;
6200 :
6201 107 : if (BaseSurfNum == 0) return; // invalid base surface, don't bother
6202 :
6203 : // Tilt and Facing (Azimuth) will be same as the Base Surface
6204 :
6205 107 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Height = Height;
6206 107 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Width = Length;
6207 :
6208 107 : SurfAzimuth = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth;
6209 107 : SurfTilt = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt;
6210 107 : CosSurfAzimuth = std::cos(SurfAzimuth * DataGlobalConstants::DegToRadians);
6211 107 : SinSurfAzimuth = std::sin(SurfAzimuth * DataGlobalConstants::DegToRadians);
6212 107 : CosSurfTilt = std::cos(SurfTilt * DataGlobalConstants::DegToRadians);
6213 107 : SinSurfTilt = std::sin(SurfTilt * DataGlobalConstants::DegToRadians);
6214 107 : BaseCosSurfAzimuth = state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosAzim;
6215 107 : BaseSinSurfAzimuth = state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).SinAzim;
6216 107 : BaseCosSurfTilt = state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosTilt;
6217 107 : BaseSinSurfTilt = state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).SinTilt;
6218 :
6219 214 : XLLC = state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).x - XCoord * BaseCosSurfAzimuth -
6220 107 : ZCoord * BaseCosSurfTilt * BaseSinSurfAzimuth;
6221 214 : YLLC = state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).y + XCoord * BaseSinSurfAzimuth -
6222 107 : ZCoord * BaseCosSurfTilt * BaseCosSurfAzimuth;
6223 107 : ZLLC = state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).z + ZCoord * BaseSinSurfTilt;
6224 :
6225 107 : XX(1) = 0.0;
6226 107 : XX(2) = 0.0;
6227 107 : XX(3) = Length;
6228 107 : XX(4) = Length;
6229 107 : YY(1) = Height;
6230 107 : YY(4) = Height;
6231 107 : YY(3) = 0.0;
6232 107 : YY(2) = 0.0;
6233 :
6234 535 : for (n = 1; n <= state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides; ++n) {
6235 428 : Vrt = n;
6236 428 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(Vrt).x = XLLC - XX(n) * CosSurfAzimuth - YY(n) * CosSurfTilt * SinSurfAzimuth;
6237 428 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(Vrt).y = YLLC + XX(n) * SinSurfAzimuth - YY(n) * CosSurfTilt * CosSurfAzimuth;
6238 428 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(Vrt).z = ZLLC + YY(n) * SinSurfTilt;
6239 : }
6240 :
6241 214 : CreateNewellAreaVector(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
6242 107 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
6243 107 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellAreaVector);
6244 107 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea = VecLength(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellAreaVector);
6245 107 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea;
6246 107 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NetAreaShadowCalc = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area;
6247 214 : CreateNewellSurfaceNormalVector(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
6248 107 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
6249 107 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector);
6250 642 : DetermineAzimuthAndTilt(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
6251 107 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
6252 : SurfAzimuth,
6253 : SurfTilt,
6254 107 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsx,
6255 107 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsy,
6256 107 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsz,
6257 107 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea,
6258 107 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector);
6259 107 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth = SurfAzimuth;
6260 107 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt = SurfTilt;
6261 107 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConvOrientation =
6262 107 : ConvectionCoefficients::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
6263 : // Sine and cosine of azimuth and tilt
6264 107 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinAzim = SinSurfAzimuth;
6265 107 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosAzim = CosSurfAzimuth;
6266 107 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinTilt = SinSurfTilt;
6267 107 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt = CosSurfTilt;
6268 266 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Window &&
6269 157 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::GlassDoor &&
6270 50 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class != SurfaceClass::Door)
6271 42 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGround = 0.5 * (1.0 - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt);
6272 : // Outward normal unit vector (pointing away from room)
6273 107 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector;
6274 428 : for (n = 1; n <= 3; ++n) {
6275 321 : if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) - 1.0) < 1.e-06)
6276 22 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) = +1.0;
6277 321 : if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) + 1.0) < 1.e-06)
6278 85 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) = -1.0;
6279 321 : if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n)) < 1.e-06)
6280 214 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) = 0.0;
6281 : }
6282 :
6283 : // IF (SurfaceTmp(SurfNum)%Class == SurfaceClass::Roof .and. SurfTilt > 80.) THEN
6284 : // WRITE(TiltString,'(F5.1)') SurfTilt
6285 : // TiltString=ADJUSTL(TiltString)
6286 : // CALL ShowWarningError(state, 'Roof/Ceiling Tilt='//TRIM(TiltString)//', much greater than expected tilt of 0,'// &
6287 : // ' for Surface='//TRIM(SurfaceTmp(SurfNum)%Name)// &
6288 : // ', in Zone='//TRIM(SurfaceTmp(SurfNum)%ZoneName))
6289 : // ENDIF
6290 : // IF (SurfaceTmp(SurfNum)%Class == SurfaceClass::Floor .and. SurfTilt < 170.) THEN
6291 : // WRITE(TiltString,'(F5.1)') SurfTilt
6292 : // TiltString=ADJUSTL(TiltString)
6293 : // CALL ShowWarningError(state, 'Floor Tilt='//TRIM(TiltString)//', much less than expected tilt of 180,'// &
6294 : // ' for Surface='//TRIM(SurfaceTmp(SurfNum)%Name)// &
6295 : // ', in Zone='//TRIM(SurfaceTmp(SurfNum)%ZoneName))
6296 : // ENDIF
6297 266 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Window ||
6298 157 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::GlassDoor ||
6299 50 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Door)
6300 65 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area *= state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier;
6301 : // Can perform tests on this surface here
6302 107 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSky = 0.5 * (1.0 + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt);
6303 : // The following IR view factors are modified in subr. SkyDifSolarShading if there are shadowing
6304 : // surfaces
6305 107 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSkyIR = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSky;
6306 107 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGroundIR = 0.5 * (1.0 - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt);
6307 :
6308 107 : Perimeter = distance(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides),
6309 107 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(1));
6310 428 : for (Vrt = 2; Vrt <= state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides; ++Vrt) {
6311 321 : Perimeter +=
6312 642 : distance(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(Vrt), state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(Vrt - 1));
6313 : }
6314 107 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Perimeter = Perimeter;
6315 :
6316 : // Call to transform vertices
6317 :
6318 107 : TransformVertsByAspect(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
6319 : }
6320 :
6321 771 : void GetAttShdSurfaceData(EnergyPlusData &state,
6322 : bool &ErrorsFound, // Error flag indicator (true if errors found)
6323 : int &SurfNum, // Count of Current SurfaceNumber
6324 : int const TotShdSubs // Number of Attached Shading SubSurfaces to obtain
6325 : )
6326 : {
6327 : // SUBROUTINE INFORMATION:
6328 : // AUTHOR Linda Lawrie
6329 : // DATE WRITTEN May 2000
6330 :
6331 : // PURPOSE OF THIS SUBROUTINE:
6332 : // This subroutine gets the HeatTransfer Surface Data,
6333 : // checks it for errors, etc.
6334 :
6335 : // Using/Aliasing
6336 : using ScheduleManager::CheckScheduleValueMinMax;
6337 : using ScheduleManager::GetScheduleIndex;
6338 : using ScheduleManager::GetScheduleMaxValue;
6339 : using ScheduleManager::GetScheduleMinValue;
6340 :
6341 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
6342 : int IOStat; // IO Status when calling get input subroutine
6343 : int NumAlphas; // Number of alpha names being passed
6344 : int NumNumbers; // Number of properties being passed
6345 : int Found; // For matching interzone surfaces
6346 : int Loop;
6347 : Real64 SchedMinValue;
6348 : Real64 SchedMaxValue;
6349 :
6350 771 : if (TotShdSubs > 0 && state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::Minimal) {
6351 1 : ShowWarningError(state, "Shading effects of Fins and Overhangs are ignored when Solar Distribution = MinimalShadowing");
6352 : }
6353 771 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
6354 771 : cCurrentModuleObject = "Shading:Zone:Detailed";
6355 771 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, Loop, NumAlphas, NumNumbers);
6356 771 : if (NumAlphas != 3) {
6357 0 : ShowSevereError(state,
6358 0 : format("{}: Object Definition indicates not = 3 Alpha Objects, Number Indicated={}", cCurrentModuleObject, NumAlphas));
6359 0 : ErrorsFound = true;
6360 : }
6361 :
6362 1430 : for (Loop = 1; Loop <= TotShdSubs; ++Loop) {
6363 4613 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
6364 : cCurrentModuleObject,
6365 : Loop,
6366 659 : state.dataIPShortCut->cAlphaArgs,
6367 : NumAlphas,
6368 659 : state.dataIPShortCut->rNumericArgs,
6369 : NumNumbers,
6370 : IOStat,
6371 659 : state.dataIPShortCut->lNumericFieldBlanks,
6372 659 : state.dataIPShortCut->lAlphaFieldBlanks,
6373 659 : state.dataIPShortCut->cAlphaFieldNames,
6374 659 : state.dataIPShortCut->cNumericFieldNames);
6375 :
6376 1318 : if (GlobalNames::VerifyUniqueInterObjectName(state,
6377 659 : state.dataSurfaceGeometry->UniqueSurfaceNames,
6378 659 : state.dataIPShortCut->cAlphaArgs(1),
6379 : cCurrentModuleObject,
6380 659 : state.dataIPShortCut->cAlphaFieldNames(1),
6381 : ErrorsFound)) {
6382 0 : continue;
6383 : }
6384 :
6385 659 : ++SurfNum;
6386 659 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name = state.dataIPShortCut->cAlphaArgs(1); // Set the Surface Name in the Derived Type
6387 659 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::Shading;
6388 659 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf = false;
6389 659 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName = state.dataIPShortCut->cAlphaArgs(2);
6390 : // The subsurface inherits properties from the base surface
6391 : // Exterior conditions, Zone, etc.
6392 : // We can figure out the base surface though, because they've all been entered
6393 1977 : Found = UtilityRoutines::FindItemInList(
6394 1977 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName, state.dataSurfaceGeometry->SurfaceTmp, state.dataSurface->TotSurfaces);
6395 659 : if (Found > 0) {
6396 : // SurfaceTmp(SurfNum)%BaseSurf=Found
6397 659 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCond;
6398 659 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtSolar;
6399 659 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtWind = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtWind;
6400 659 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone =
6401 659 : state.dataSurfaceGeometry->SurfaceTmp(Found).Zone; // Necessary to do relative coordinates in GetVertices below
6402 1318 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName =
6403 1318 : state.dataSurfaceGeometry->SurfaceTmp(Found).ZoneName; // Necessary to have surface drawn in OutputReports
6404 : } else {
6405 0 : ShowSevereError(state,
6406 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
6407 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2));
6408 0 : ErrorsFound = true;
6409 : }
6410 659 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnenteredAdjacentZoneSurface) {
6411 0 : ShowSevereError(state,
6412 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
6413 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2));
6414 0 : ShowContinueError(state, "...trying to attach a shading device to an interzone surface.");
6415 0 : ErrorsFound = true;
6416 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond =
6417 : ExternalEnvironment; // reset so program won't crash during "add surfaces"
6418 : }
6419 659 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnreconciledZoneSurface) {
6420 0 : ShowSevereError(state,
6421 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
6422 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2));
6423 0 : ShowContinueError(state, "...trying to attach a shading device to an interior surface.");
6424 0 : ErrorsFound = true;
6425 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond =
6426 : ExternalEnvironment; // reset so program won't crash during "add surfaces"
6427 : }
6428 :
6429 659 : if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) {
6430 596 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(3));
6431 596 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex == 0) {
6432 0 : ShowSevereError(state,
6433 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", " +
6434 0 : state.dataIPShortCut->cAlphaFieldNames(3) + " not found=\"" + state.dataIPShortCut->cAlphaArgs(3));
6435 0 : ErrorsFound = true;
6436 : }
6437 : } else {
6438 63 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex = 0;
6439 : }
6440 659 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex != 0) {
6441 596 : if (!CheckScheduleValueMinMax(state, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex, ">=", 0.0, "<=", 1.0)) {
6442 0 : ShowSevereError(state,
6443 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", " +
6444 0 : state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) +
6445 : "\", values not in range [0,1].");
6446 0 : ErrorsFound = true;
6447 : }
6448 596 : SchedMinValue = GetScheduleMinValue(state, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex);
6449 596 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedMinValue = SchedMinValue;
6450 596 : SchedMaxValue = GetScheduleMaxValue(state, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex);
6451 596 : if (SchedMinValue == 1.0) {
6452 0 : ShowWarningError(state,
6453 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", " +
6454 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) +
6455 : "\", is always transparent.");
6456 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).IsTransparent = true;
6457 : }
6458 596 : if (SchedMinValue < 0.0) {
6459 0 : ShowSevereError(state,
6460 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", " +
6461 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) +
6462 : "\", has schedule values < 0.");
6463 0 : ShowContinueError(state, "...Schedule values < 0 have no meaning for shading elements.");
6464 : }
6465 596 : if (SchedMaxValue > 0.0) {
6466 8 : state.dataSolarShading->anyScheduledShadingSurface = true;
6467 : }
6468 596 : if (SchedMaxValue > 1.0) {
6469 0 : ShowSevereError(state,
6470 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", " +
6471 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) +
6472 : "\", has schedule values > 1.");
6473 0 : ShowContinueError(state, "...Schedule values > 1 have no meaning for shading elements.");
6474 : }
6475 596 : if (std::abs(SchedMinValue - SchedMaxValue) > 1.0e-6) {
6476 0 : state.dataSurface->ShadingTransmittanceVaries = true;
6477 : }
6478 : }
6479 659 : if (state.dataIPShortCut->lNumericFieldBlanks(1) || state.dataIPShortCut->rNumericArgs(1) == DataGlobalConstants::AutoCalculate) {
6480 2 : state.dataIPShortCut->rNumericArgs(1) = (NumNumbers - 1) / 3;
6481 2 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = state.dataIPShortCut->rNumericArgs(1);
6482 2 : if (mod(NumNumbers - 1, 3) != 0) {
6483 0 : ShowWarningError(state,
6484 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", " +
6485 0 : format("{} not even multiple of 3. Will read in {}",
6486 0 : state.dataIPShortCut->cNumericFieldNames(1),
6487 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides));
6488 : }
6489 2 : if (state.dataIPShortCut->rNumericArgs(1) < 3) {
6490 0 : ShowSevereError(state,
6491 0 : format("{}=\"{}\", {} (autocalculate) must be >= 3. Only {} provided.",
6492 : cCurrentModuleObject,
6493 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
6494 0 : state.dataIPShortCut->cNumericFieldNames(1),
6495 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides));
6496 0 : ErrorsFound = true;
6497 0 : continue;
6498 : }
6499 : } else {
6500 657 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = state.dataIPShortCut->rNumericArgs(1);
6501 : }
6502 659 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.allocate(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
6503 659 : GetVertices(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides, state.dataIPShortCut->rNumericArgs({2, _}));
6504 659 : CheckConvexity(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
6505 : // IF (SurfaceTmp(SurfNum)%Sides == 3) THEN
6506 : // CALL ShowWarningError(state, TRIM(cCurrentModuleObject)//'="'//TRIM(SurfaceTmp(SurfNum)%Name)// &
6507 : // ' should not be triangular.')
6508 : // CALL ShowContinueError(state, '...Check results carefully.')
6509 : // ErrorsFound=.TRUE.
6510 : // ENDIF
6511 : // Reset surface to be "detached"
6512 659 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf = 0;
6513 : // SurfaceTmp(SurfNum)%BaseSurfName=' '
6514 659 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone = 0;
6515 : // SurfaceTmp(SurfNum)%ZoneName=' '
6516 659 : if (state.dataReportFlag->MakeMirroredAttachedShading) {
6517 659 : MakeMirrorSurface(state, SurfNum);
6518 : }
6519 : }
6520 771 : }
6521 :
6522 771 : void GetSimpleShdSurfaceData(EnergyPlusData &state,
6523 : bool &ErrorsFound, // Error flag indicator (true if errors found)
6524 : int &SurfNum, // Count of Current SurfaceNumber
6525 : int const TotOverhangs, // Number of Overhangs to obtain
6526 : int const TotOverhangsProjection, // Number of Overhangs (projection) to obtain
6527 : int const TotFins, // Number of Fins to obtain
6528 : int const TotFinsProjection // Number of Fins (projection) to obtain
6529 : )
6530 : {
6531 :
6532 : // SUBROUTINE INFORMATION:
6533 : // AUTHOR Linda Lawrie
6534 : // DATE WRITTEN January 2009
6535 : // MODIFIED na
6536 : // RE-ENGINEERED na
6537 :
6538 : // PURPOSE OF THIS SUBROUTINE:
6539 : // Get simple overhang and fin descriptions.
6540 :
6541 : // Using/Aliasing
6542 : using namespace Vectors;
6543 :
6544 : // SUBROUTINE PARAMETER DEFINITIONS:
6545 771 : static Array1D_string const cModuleObjects(4, {"Shading:Overhang", "Shading:Overhang:Projection", "Shading:Fin", "Shading:Fin:Projection"});
6546 :
6547 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
6548 : int Item;
6549 : int ItemsToGet;
6550 : int Loop;
6551 : int NumAlphas;
6552 : int NumNumbers;
6553 : int IOStat; // IO Status when calling get input subroutine
6554 : int Found; // For matching base surfaces
6555 : Real64 Depth;
6556 : Real64 Length;
6557 : Real64 Xp;
6558 : Real64 Yp;
6559 : Real64 Zp;
6560 : Real64 XLLC;
6561 : Real64 YLLC;
6562 : int BaseSurfNum;
6563 : Real64 TiltAngle;
6564 : bool MakeFin;
6565 :
6566 779 : if ((TotOverhangs + TotOverhangsProjection + TotFins + TotFinsProjection) > 0 &&
6567 8 : state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::Minimal) {
6568 0 : ShowWarningError(state, "Shading effects of Fins and Overhangs are ignored when Solar Distribution = MinimalShadowing");
6569 : }
6570 771 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
6571 3855 : for (Item = 1; Item <= 4; ++Item) {
6572 :
6573 3084 : cCurrentModuleObject = cModuleObjects(Item);
6574 3084 : if (Item == 1) {
6575 771 : ItemsToGet = TotOverhangs;
6576 2313 : } else if (Item == 2) {
6577 771 : ItemsToGet = TotOverhangsProjection;
6578 1542 : } else if (Item == 3) {
6579 771 : ItemsToGet = TotFins;
6580 : } else { // ! (Item == 4) THEN
6581 771 : ItemsToGet = TotFinsProjection;
6582 : }
6583 :
6584 3117 : for (Loop = 1; Loop <= ItemsToGet; ++Loop) {
6585 231 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
6586 : cCurrentModuleObject,
6587 : Loop,
6588 33 : state.dataIPShortCut->cAlphaArgs,
6589 : NumAlphas,
6590 33 : state.dataIPShortCut->rNumericArgs,
6591 : NumNumbers,
6592 : IOStat,
6593 33 : state.dataIPShortCut->lNumericFieldBlanks,
6594 33 : state.dataIPShortCut->lAlphaFieldBlanks,
6595 33 : state.dataIPShortCut->cAlphaFieldNames,
6596 33 : state.dataIPShortCut->cNumericFieldNames);
6597 :
6598 66 : if (GlobalNames::VerifyUniqueInterObjectName(state,
6599 33 : state.dataSurfaceGeometry->UniqueSurfaceNames,
6600 33 : state.dataIPShortCut->cAlphaArgs(1),
6601 : cCurrentModuleObject,
6602 33 : state.dataIPShortCut->cAlphaFieldNames(1),
6603 : ErrorsFound)) {
6604 0 : continue;
6605 : }
6606 :
6607 33 : ++SurfNum;
6608 33 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name = state.dataIPShortCut->cAlphaArgs(1); // Set the Surface Name in the Derived Type
6609 33 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::Shading;
6610 33 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf = false;
6611 : // this object references a window or door....
6612 99 : Found = UtilityRoutines::FindItemInList(
6613 99 : state.dataIPShortCut->cAlphaArgs(2), state.dataSurfaceGeometry->SurfaceTmp, state.dataSurface->TotSurfaces);
6614 33 : if (Found > 0) {
6615 33 : BaseSurfNum = state.dataSurfaceGeometry->SurfaceTmp(Found).BaseSurf;
6616 33 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName = state.dataSurfaceGeometry->SurfaceTmp(Found).BaseSurfName;
6617 33 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCond;
6618 33 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtSolar;
6619 33 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtWind = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtWind;
6620 33 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone =
6621 33 : state.dataSurfaceGeometry->SurfaceTmp(Found).Zone; // Necessary to do relative coordinates in GetVertices below
6622 66 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName =
6623 66 : state.dataSurfaceGeometry->SurfaceTmp(Found).ZoneName; // Necessary to have surface drawn in OutputReports
6624 : } else {
6625 0 : ShowSevereError(state,
6626 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
6627 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2));
6628 0 : ErrorsFound = true;
6629 0 : continue;
6630 : }
6631 33 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnenteredAdjacentZoneSurface) {
6632 0 : ShowSevereError(state,
6633 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
6634 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2));
6635 0 : ShowContinueError(state, "...trying to attach a shading device to an interzone surface.");
6636 0 : ErrorsFound = true;
6637 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond =
6638 : ExternalEnvironment; // reset so program won't crash during "add surfaces"
6639 : }
6640 33 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnreconciledZoneSurface) {
6641 0 : ShowSevereError(state,
6642 0 : cCurrentModuleObject + "=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " +
6643 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2));
6644 0 : ShowContinueError(state, "...trying to attach a shading device to an interior surface.");
6645 0 : ErrorsFound = true;
6646 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond =
6647 : ExternalEnvironment; // reset so program won't crash during "add surfaces"
6648 : }
6649 :
6650 33 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex = 0;
6651 :
6652 : //===== Overhang =====
6653 :
6654 33 : if (Item < 3) {
6655 : // Found is the surface window or door.
6656 : // N1, \field Height above Window or Door
6657 : // \units m
6658 : // N2, \field Tilt Angle from Window/Door
6659 : // \units deg
6660 : // \default 90
6661 : // \minimum 0
6662 : // \maximum 180
6663 : // N3, \field Left extension from Window/Door Width
6664 : // \units m
6665 : // N4, \field Right extension from Window/Door Width
6666 : // \note N3 + N4 + Window/Door Width is Overhang Length
6667 : // \units m
6668 : // N5; \field Depth
6669 : // \units m
6670 : // for projection option:
6671 : // N5; \field Depth as Fraction of Window/Door Height
6672 : // \units m
6673 48 : Length = state.dataIPShortCut->rNumericArgs(3) + state.dataIPShortCut->rNumericArgs(4) +
6674 24 : state.dataSurfaceGeometry->SurfaceTmp(Found).Width;
6675 24 : if (Item == 1) {
6676 23 : Depth = state.dataIPShortCut->rNumericArgs(5);
6677 1 : } else if (Item == 2) {
6678 1 : Depth = state.dataIPShortCut->rNumericArgs(5) * state.dataSurfaceGeometry->SurfaceTmp(Found).Height;
6679 : }
6680 :
6681 24 : if (Length * Depth <= 0.0) {
6682 0 : ShowSevereError(state,
6683 0 : format("{}=\"{}\", illegal surface area=[{:.2R}]. Surface will NOT be entered.",
6684 : cCurrentModuleObject,
6685 0 : state.dataIPShortCut->cAlphaArgs(1),
6686 0 : Length * Depth));
6687 0 : continue;
6688 : }
6689 :
6690 24 : TiltAngle = state.dataSurfaceGeometry->SurfaceTmp(Found).Tilt + state.dataIPShortCut->rNumericArgs(2);
6691 24 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt = TiltAngle;
6692 24 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConvOrientation =
6693 24 : ConvectionCoefficients::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
6694 24 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth = state.dataSurfaceGeometry->SurfaceTmp(Found).Azimuth;
6695 :
6696 : // Make it relative to surface origin.....
6697 24 : Xp = state.dataSurfaceGeometry->SurfaceTmp(Found).Vertex(2).x - state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).x;
6698 24 : Yp = state.dataSurfaceGeometry->SurfaceTmp(Found).Vertex(2).y - state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).y;
6699 24 : Zp = state.dataSurfaceGeometry->SurfaceTmp(Found).Vertex(2).z - state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).z;
6700 :
6701 48 : XLLC = -Xp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosAzim +
6702 24 : Yp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).SinAzim;
6703 :
6704 24 : YLLC =
6705 48 : -Xp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).SinAzim *
6706 48 : state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosTilt -
6707 24 : Yp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosAzim * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosTilt +
6708 24 : Zp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).SinTilt;
6709 :
6710 24 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = 4;
6711 24 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.allocate(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
6712 :
6713 48 : MakeRelativeRectangularVertices(state,
6714 : BaseSurfNum,
6715 : SurfNum,
6716 24 : XLLC - state.dataIPShortCut->rNumericArgs(3),
6717 24 : YLLC + state.dataSurfaceGeometry->SurfaceTmp(Found).Height +
6718 24 : state.dataIPShortCut->rNumericArgs(1),
6719 : Length,
6720 : Depth);
6721 :
6722 : // Reset surface to be "detached"
6723 : // SurfaceTmp(SurfNum)%BaseSurfName=' '
6724 : // SurfaceTmp(SurfNum)%ZoneName=' '
6725 :
6726 24 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf = 0;
6727 24 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone = 0;
6728 :
6729 : // and mirror
6730 24 : if (state.dataReportFlag->MakeMirroredAttachedShading) {
6731 24 : MakeMirrorSurface(state, SurfNum);
6732 : }
6733 :
6734 : } else { // Fins
6735 :
6736 : //===== Fins =====
6737 :
6738 : //===== Left Fin =====
6739 :
6740 : // N1, \field Left Extension from Window/Door
6741 : // \units m
6742 : // N2, \field Left Distance Above Top of Window
6743 : // \units m
6744 : // N3, \field Left Distance Below Bottom of Window
6745 : // \units m
6746 : // \note N2 + N3 + height of Window/Door is height of Fin
6747 : // N4, \field Left Tilt Angle from Window/Door
6748 : // \units deg
6749 : // \default 90
6750 : // \minimum 0
6751 : // \maximum 180
6752 : // N5, \field Left Depth
6753 : // \units m
6754 : // for projection option:
6755 : // N5, \field Left Depth as Fraction of Window/Door Width
6756 : // \units m
6757 9 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + " Left";
6758 18 : Length = state.dataIPShortCut->rNumericArgs(2) + state.dataIPShortCut->rNumericArgs(3) +
6759 9 : state.dataSurfaceGeometry->SurfaceTmp(Found).Height;
6760 9 : if (Item == 3) {
6761 8 : Depth = state.dataIPShortCut->rNumericArgs(5);
6762 1 : } else if (Item == 4) {
6763 1 : Depth = state.dataIPShortCut->rNumericArgs(5) * state.dataSurfaceGeometry->SurfaceTmp(Found).Width;
6764 : }
6765 :
6766 9 : MakeFin = true;
6767 9 : if (Length * Depth <= 0.0) {
6768 0 : ShowWarningError(state,
6769 0 : format("{}=Left Fin of \"{}\", illegal surface area=[{:.2R}]. Surface will NOT be entered.",
6770 : cCurrentModuleObject,
6771 0 : state.dataIPShortCut->cAlphaArgs(1),
6772 0 : Length * Depth));
6773 0 : MakeFin = false;
6774 : }
6775 :
6776 9 : if (MakeFin) {
6777 9 : TiltAngle = state.dataSurfaceGeometry->SurfaceTmp(Found).Tilt;
6778 9 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt = TiltAngle;
6779 9 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConvOrientation =
6780 9 : ConvectionCoefficients::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
6781 9 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth =
6782 9 : state.dataSurfaceGeometry->SurfaceTmp(Found).Azimuth - (180.0 - state.dataIPShortCut->rNumericArgs(4));
6783 :
6784 : // Make it relative to surface origin.....
6785 :
6786 9 : Xp =
6787 9 : state.dataSurfaceGeometry->SurfaceTmp(Found).Vertex(2).x - state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).x;
6788 9 : Yp =
6789 9 : state.dataSurfaceGeometry->SurfaceTmp(Found).Vertex(2).y - state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).y;
6790 9 : Zp =
6791 9 : state.dataSurfaceGeometry->SurfaceTmp(Found).Vertex(2).z - state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).z;
6792 :
6793 18 : XLLC = -Xp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosAzim +
6794 9 : Yp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).SinAzim;
6795 :
6796 27 : YLLC = -Xp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).SinAzim *
6797 18 : state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosTilt -
6798 18 : Yp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosAzim *
6799 9 : state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosTilt +
6800 9 : Zp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).SinTilt;
6801 :
6802 9 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosAzim =
6803 9 : std::cos(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth * DataGlobalConstants::DegToRadians);
6804 9 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinAzim =
6805 9 : std::sin(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth * DataGlobalConstants::DegToRadians);
6806 9 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt =
6807 9 : std::cos(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt * DataGlobalConstants::DegToRadians);
6808 9 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinTilt =
6809 9 : std::sin(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt * DataGlobalConstants::DegToRadians);
6810 :
6811 9 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = 4;
6812 9 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.allocate(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
6813 :
6814 27 : MakeRelativeRectangularVertices(state,
6815 : BaseSurfNum,
6816 : SurfNum,
6817 9 : XLLC - state.dataIPShortCut->rNumericArgs(1),
6818 9 : YLLC - state.dataIPShortCut->rNumericArgs(3),
6819 : -Depth,
6820 : Length);
6821 :
6822 : // Reset surface to be "detached"
6823 : // SurfaceTmp(SurfNum)%BaseSurfName=' '
6824 : // SurfaceTmp(SurfNum)%ZoneName=' '
6825 :
6826 9 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf = 0;
6827 9 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone = 0;
6828 :
6829 : // and mirror
6830 9 : if (state.dataReportFlag->MakeMirroredAttachedShading) {
6831 9 : MakeMirrorSurface(state, SurfNum);
6832 : }
6833 : } else {
6834 0 : --SurfNum;
6835 : }
6836 :
6837 : //===== Right Fin =====
6838 :
6839 : // N6, \field Right Extension from Window/Door
6840 : // \units m
6841 : // N7, \field Right Distance Above Top of Window
6842 : // \units m
6843 : // N8, \field Right Distance Below Bottom of Window
6844 : // \note N7 + N8 + height of Window/Door is height of Fin
6845 : // \units m
6846 : // N9, \field Right Tilt Angle from Window/Door
6847 : // \units deg
6848 : // \default 90
6849 : // \minimum 0
6850 : // \maximum 180
6851 : // N10; \field Right Depth
6852 : // \units m
6853 : // for projection option:
6854 : // N10; \field Right Depth as Fraction of Window/Door Width
6855 : // \units m
6856 :
6857 9 : ++SurfNum;
6858 18 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name =
6859 27 : state.dataIPShortCut->cAlphaArgs(1) + " Right"; // Set the Surface Name in the Derived Type
6860 9 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::Shading;
6861 9 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf = false;
6862 9 : BaseSurfNum = state.dataSurfaceGeometry->SurfaceTmp(Found).BaseSurf;
6863 9 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName = state.dataSurfaceGeometry->SurfaceTmp(Found).BaseSurfName;
6864 9 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCond;
6865 9 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtSolar;
6866 9 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtWind = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtWind;
6867 9 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone =
6868 9 : state.dataSurfaceGeometry->SurfaceTmp(Found).Zone; // Necessary to do relative coordinates in GetVertices below
6869 18 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName =
6870 18 : state.dataSurfaceGeometry->SurfaceTmp(Found).ZoneName; // Necessary to have surface drawn in OutputReports
6871 :
6872 9 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex = 0;
6873 18 : Length = state.dataIPShortCut->rNumericArgs(7) + state.dataIPShortCut->rNumericArgs(8) +
6874 9 : state.dataSurfaceGeometry->SurfaceTmp(Found).Height;
6875 9 : if (Item == 3) {
6876 8 : Depth = state.dataIPShortCut->rNumericArgs(10);
6877 1 : } else if (Item == 4) {
6878 1 : Depth = state.dataIPShortCut->rNumericArgs(10) * state.dataSurfaceGeometry->SurfaceTmp(Found).Width;
6879 : }
6880 :
6881 9 : MakeFin = true;
6882 9 : if (Length * Depth <= 0.0) {
6883 0 : ShowWarningError(state,
6884 0 : format("{}=Right Fin of \"{}\", illegal surface area=[{:.2R}]. Surface will NOT be entered.",
6885 : cCurrentModuleObject,
6886 0 : state.dataIPShortCut->cAlphaArgs(1),
6887 0 : Length * Depth));
6888 0 : MakeFin = false;
6889 : }
6890 :
6891 9 : if (MakeFin) {
6892 : // Make it relative to surface origin.....
6893 :
6894 9 : Xp =
6895 9 : state.dataSurfaceGeometry->SurfaceTmp(Found).Vertex(2).x - state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).x;
6896 9 : Yp =
6897 9 : state.dataSurfaceGeometry->SurfaceTmp(Found).Vertex(2).y - state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).y;
6898 9 : Zp =
6899 9 : state.dataSurfaceGeometry->SurfaceTmp(Found).Vertex(2).z - state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).Vertex(2).z;
6900 :
6901 18 : XLLC = -Xp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosAzim +
6902 9 : Yp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).SinAzim;
6903 :
6904 27 : YLLC = -Xp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).SinAzim *
6905 18 : state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosTilt -
6906 18 : Yp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosAzim *
6907 9 : state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).CosTilt +
6908 9 : Zp * state.dataSurfaceGeometry->SurfaceTmp(BaseSurfNum).SinTilt;
6909 :
6910 9 : TiltAngle = state.dataSurfaceGeometry->SurfaceTmp(Found).Tilt;
6911 9 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt = TiltAngle;
6912 9 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConvOrientation =
6913 9 : ConvectionCoefficients::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
6914 9 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth =
6915 9 : state.dataSurfaceGeometry->SurfaceTmp(Found).Azimuth - (180.0 - state.dataIPShortCut->rNumericArgs(9));
6916 9 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosAzim =
6917 9 : std::cos(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth * DataGlobalConstants::DegToRadians);
6918 9 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinAzim =
6919 9 : std::sin(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth * DataGlobalConstants::DegToRadians);
6920 9 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt =
6921 9 : std::cos(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt * DataGlobalConstants::DegToRadians);
6922 9 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinTilt =
6923 9 : std::sin(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt * DataGlobalConstants::DegToRadians);
6924 :
6925 9 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides = 4;
6926 9 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex.allocate(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
6927 :
6928 27 : MakeRelativeRectangularVertices(state,
6929 : BaseSurfNum,
6930 : SurfNum,
6931 9 : XLLC + state.dataSurfaceGeometry->SurfaceTmp(Found).Width +
6932 9 : state.dataIPShortCut->rNumericArgs(6),
6933 9 : YLLC - state.dataIPShortCut->rNumericArgs(8),
6934 : -Depth,
6935 : Length);
6936 :
6937 : // Reset surface to be "detached"
6938 : // SurfaceTmp(SurfNum)%BaseSurfName=' '
6939 : // SurfaceTmp(SurfNum)%ZoneName=' '
6940 :
6941 9 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf = 0;
6942 9 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone = 0;
6943 :
6944 : // and mirror
6945 9 : if (state.dataReportFlag->MakeMirroredAttachedShading) {
6946 9 : MakeMirrorSurface(state, SurfNum);
6947 : }
6948 : } else {
6949 0 : --SurfNum;
6950 : }
6951 : }
6952 : }
6953 : }
6954 771 : }
6955 :
6956 771 : void GetIntMassSurfaceData(EnergyPlusData &state,
6957 : bool &ErrorsFound, // Error flag indicator (true if errors found)
6958 : int &SurfNum // Count of Current SurfaceNumber
6959 : )
6960 : {
6961 :
6962 : // SUBROUTINE INFORMATION:
6963 : // AUTHOR Linda Lawrie
6964 : // DATE WRITTEN May 2000
6965 : // MODIFIED na
6966 : // RE-ENGINEERED na
6967 :
6968 : // PURPOSE OF THIS SUBROUTINE:
6969 : // This subroutine gets the Internal Surface Data,
6970 : // checks it for errors, etc.
6971 :
6972 : // METHODOLOGY EMPLOYED:
6973 : // na
6974 :
6975 : // REFERENCES:
6976 : // Internal Mass Surface Definition
6977 : // Surface:HeatTransfer:InternalMass,
6978 : // \note used to describe internal zone surface area that does not need to be part of geometric representation
6979 : // A1 , \field User Supplied Surface Name
6980 : // \type alpha
6981 : // \reference SurfaceNames
6982 : // A2 , \field Construction Name of the Surface
6983 : // \note To be matched with a construction in this input file
6984 : // \type object-list
6985 : // \object-list ConstructionNames
6986 : // A3 , \field Interior Environment
6987 : // \note Zone the surface is a part of
6988 : // \type object-list
6989 : // \object-list ZoneNames
6990 : // N1, \field View factor to Person (to people?)
6991 : // \type real
6992 : // \note from the interior of the surface
6993 : // N2 ; \field Surface area
6994 : // \units m2
6995 :
6996 : // Using/Aliasing
6997 : using namespace Vectors;
6998 : using General::CheckCreatedZoneItemName;
6999 :
7000 : // SUBROUTINE PARAMETER DEFINITIONS:
7001 : static constexpr std::string_view RoutineName("GetIntMassSurfaceData: ");
7002 :
7003 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
7004 : int IOStat; // IO Status when calling get input subroutine
7005 : int SurfaceNumAlpha; // Number of material alpha names being passed
7006 : int SurfaceNumArg; // Number of material properties being passed
7007 : int ZoneNum; // index to a zone
7008 771 : int NumIntMassSurfaces(0); // total count of internal mass surfaces
7009 : bool errFlag; // local error flag
7010 771 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
7011 771 : cCurrentModuleObject = "InternalMass";
7012 771 : int TotIntMass = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
7013 771 : if (TotIntMass == 0) return;
7014 :
7015 164 : state.dataSurface->IntMassObjects.allocate(TotIntMass);
7016 :
7017 : // scan for use of Zone lists in InternalMass objects
7018 164 : errFlag = false;
7019 164 : NumIntMassSurfaces = 0;
7020 2446 : for (int Item = 1; Item <= TotIntMass; ++Item) {
7021 15974 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
7022 : cCurrentModuleObject,
7023 : Item,
7024 2282 : state.dataIPShortCut->cAlphaArgs,
7025 : SurfaceNumAlpha,
7026 2282 : state.dataIPShortCut->rNumericArgs,
7027 : SurfaceNumArg,
7028 : IOStat,
7029 2282 : state.dataIPShortCut->lNumericFieldBlanks,
7030 2282 : state.dataIPShortCut->lAlphaFieldBlanks,
7031 2282 : state.dataIPShortCut->cAlphaFieldNames,
7032 2282 : state.dataIPShortCut->cNumericFieldNames);
7033 :
7034 4564 : if (GlobalNames::VerifyUniqueInterObjectName(state,
7035 2282 : state.dataSurfaceGeometry->UniqueSurfaceNames,
7036 2282 : state.dataIPShortCut->cAlphaArgs(1),
7037 : cCurrentModuleObject,
7038 2282 : state.dataIPShortCut->cAlphaFieldNames(1),
7039 : ErrorsFound)) {
7040 0 : continue;
7041 : }
7042 :
7043 2282 : state.dataSurface->IntMassObjects(Item).Name = state.dataIPShortCut->cAlphaArgs(1);
7044 2282 : state.dataSurface->IntMassObjects(Item).GrossArea = state.dataIPShortCut->rNumericArgs(1);
7045 6846 : state.dataSurface->IntMassObjects(Item).Construction = UtilityRoutines::FindItemInList(
7046 6846 : state.dataIPShortCut->cAlphaArgs(2), state.dataConstruction->Construct, state.dataHeatBal->TotConstructs);
7047 2282 : state.dataSurface->IntMassObjects(Item).ZoneOrZoneListName = state.dataIPShortCut->cAlphaArgs(3);
7048 2282 : int Item1 = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(3), state.dataHeatBal->Zone, state.dataGlobal->NumOfZones);
7049 2282 : int ZLItem = 0;
7050 2282 : if (Item1 == 0 && state.dataHeatBal->NumOfZoneLists > 0)
7051 1 : ZLItem = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(3), state.dataHeatBal->ZoneList);
7052 2282 : if (Item1 > 0) {
7053 2281 : if (state.dataIPShortCut->lAlphaFieldBlanks(4)) {
7054 2281 : ++NumIntMassSurfaces;
7055 : }
7056 2281 : state.dataSurface->IntMassObjects(Item).NumOfZones = 1;
7057 2281 : state.dataSurface->IntMassObjects(Item).ZoneListActive = false;
7058 2281 : state.dataSurface->IntMassObjects(Item).ZoneOrZoneListPtr = Item1;
7059 1 : } else if (ZLItem > 0) {
7060 1 : NumIntMassSurfaces += state.dataHeatBal->ZoneList(ZLItem).NumOfZones;
7061 1 : state.dataSurface->IntMassObjects(Item).NumOfZones = state.dataHeatBal->ZoneList(ZLItem).NumOfZones;
7062 1 : state.dataSurface->IntMassObjects(Item).ZoneListActive = true;
7063 1 : state.dataSurface->IntMassObjects(Item).ZoneOrZoneListPtr = ZLItem;
7064 : } else {
7065 0 : ShowSevereError(state,
7066 0 : cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " +
7067 0 : state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) + "\" not found.");
7068 0 : ++SurfNum;
7069 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::Invalid;
7070 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName = "Unknown Zone";
7071 0 : ErrorsFound = true;
7072 0 : errFlag = true;
7073 : }
7074 :
7075 2282 : if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) {
7076 0 : state.dataSurface->IntMassObjects(Item).spaceOrSpaceListName = state.dataIPShortCut->cAlphaArgs(4);
7077 0 : int Item1 = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(4), state.dataHeatBal->space);
7078 0 : int SLItem = 0;
7079 0 : if (Item1 == 0 && int(state.dataHeatBal->spaceList.size()) > 0)
7080 0 : SLItem = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(4), state.dataHeatBal->spaceList);
7081 0 : if (Item1 > 0) {
7082 0 : ++NumIntMassSurfaces;
7083 0 : state.dataSurface->IntMassObjects(Item).numOfSpaces = 1;
7084 0 : state.dataSurface->IntMassObjects(Item).spaceListActive = false;
7085 0 : state.dataSurface->IntMassObjects(Item).spaceOrSpaceListPtr = Item1;
7086 0 : if (!state.dataSurface->IntMassObjects(Item).ZoneListActive) {
7087 0 : if (state.dataHeatBal->space(Item1).zoneNum != state.dataSurface->IntMassObjects(Item).ZoneOrZoneListPtr) {
7088 0 : ShowSevereError(state,
7089 0 : cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " +
7090 0 : state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataIPShortCut->cAlphaArgs(4) +
7091 0 : "\" is not part of Zone =\"" + state.dataIPShortCut->cAlphaArgs(3) + "\".");
7092 0 : ErrorsFound = true;
7093 0 : errFlag = true;
7094 : }
7095 : }
7096 0 : } else if (SLItem > 0) {
7097 0 : int numOfSpaces = int(state.dataHeatBal->spaceList(SLItem).numListSpaces);
7098 0 : NumIntMassSurfaces += numOfSpaces;
7099 0 : state.dataSurface->IntMassObjects(Item).numOfSpaces = numOfSpaces;
7100 0 : state.dataSurface->IntMassObjects(Item).spaceListActive = true;
7101 0 : state.dataSurface->IntMassObjects(Item).spaceOrSpaceListPtr = SLItem;
7102 : } else {
7103 0 : ShowSevereError(state,
7104 0 : cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " +
7105 0 : state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\" not found.");
7106 0 : ++SurfNum;
7107 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::Invalid;
7108 0 : ErrorsFound = true;
7109 0 : errFlag = true;
7110 : }
7111 : }
7112 :
7113 2282 : if (errFlag) {
7114 0 : ShowSevereError(state, std::string{RoutineName} + "Errors with invalid names in " + cCurrentModuleObject + " objects.");
7115 0 : ShowContinueError(state, "...These will not be read in. Other errors may occur.");
7116 0 : NumIntMassSurfaces = 0;
7117 : }
7118 :
7119 2282 : if (state.dataSurface->IntMassObjects(Item).Construction == 0) {
7120 0 : ErrorsFound = true;
7121 0 : ShowSevereError(state,
7122 0 : cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", " +
7123 0 : state.dataIPShortCut->cAlphaFieldNames(2) + " not found=" + state.dataIPShortCut->cAlphaArgs(2));
7124 2282 : } else if (state.dataConstruction->Construct(state.dataSurface->IntMassObjects(Item).Construction).TypeIsWindow) {
7125 0 : ErrorsFound = true;
7126 0 : ShowSevereError(state,
7127 0 : cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", invalid " +
7128 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) +
7129 : "\" - has Window materials.");
7130 : } else {
7131 2282 : state.dataConstruction->Construct(state.dataSurface->IntMassObjects(Item).Construction).IsUsed = true;
7132 : }
7133 : }
7134 :
7135 164 : if (NumIntMassSurfaces > 0) {
7136 164 : int spaceNum = 0;
7137 2446 : for (int Loop = 1; Loop <= TotIntMass; ++Loop) {
7138 2282 : int numberOfZonesOrSpaces = 1;
7139 2282 : if (state.dataSurface->IntMassObjects(Loop).ZoneListActive) {
7140 1 : numberOfZonesOrSpaces = state.dataSurface->IntMassObjects(Loop).NumOfZones;
7141 2281 : } else if (state.dataSurface->IntMassObjects(Loop).spaceListActive) {
7142 0 : numberOfZonesOrSpaces = state.dataSurface->IntMassObjects(Loop).numOfSpaces;
7143 : }
7144 :
7145 4566 : for (int Item1 = 1; Item1 <= numberOfZonesOrSpaces; ++Item1) {
7146 :
7147 2284 : ++SurfNum;
7148 :
7149 2284 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction = state.dataSurface->IntMassObjects(Loop).Construction;
7150 2284 : if (!state.dataSurface->IntMassObjects(Loop).ZoneListActive && !state.dataSurface->IntMassObjects(Loop).spaceListActive) {
7151 2281 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone = state.dataSurface->IntMassObjects(Loop).ZoneOrZoneListPtr;
7152 2281 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).spaceNum = state.dataSurface->IntMassObjects(Loop).spaceOrSpaceListPtr;
7153 2281 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name = state.dataSurface->IntMassObjects(Loop).Name;
7154 2281 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::IntMass;
7155 2281 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName = state.dataSurface->IntMassObjects(Loop).ZoneOrZoneListName;
7156 2281 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf = true;
7157 : } else {
7158 3 : if (state.dataSurface->IntMassObjects(Loop).ZoneListActive) {
7159 18 : CheckCreatedZoneItemName(
7160 : state,
7161 : RoutineName,
7162 : cCurrentModuleObject,
7163 : state.dataHeatBal
7164 3 : ->Zone(state.dataHeatBal->ZoneList(state.dataSurface->IntMassObjects(Loop).ZoneOrZoneListPtr).Zone(Item1))
7165 : .Name,
7166 3 : state.dataHeatBal->ZoneList(state.dataSurface->IntMassObjects(Loop).ZoneOrZoneListPtr).MaxZoneNameLength,
7167 3 : state.dataSurface->IntMassObjects(Loop).Name,
7168 3 : state.dataSurfaceGeometry->SurfaceTmp,
7169 3 : SurfNum - 1,
7170 3 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
7171 : errFlag);
7172 :
7173 3 : ZoneNum = state.dataHeatBal->ZoneList(state.dataSurface->IntMassObjects(Loop).ZoneOrZoneListPtr).Zone(Item1);
7174 0 : } else if (state.dataSurface->IntMassObjects(Loop).spaceListActive) {
7175 0 : spaceNum = state.dataHeatBal->spaceList(state.dataSurface->IntMassObjects(Loop).spaceOrSpaceListPtr).spaces(Item1);
7176 0 : ZoneNum = state.dataHeatBal->space(spaceNum).zoneNum;
7177 0 : const std::string spaceName = state.dataHeatBal->space(spaceNum).Name;
7178 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name = spaceName + ' ' + state.dataSurface->IntMassObjects(Loop).Name;
7179 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).spaceNum = spaceNum;
7180 : }
7181 3 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone = ZoneNum;
7182 3 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class = SurfaceClass::IntMass;
7183 3 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName = state.dataHeatBal->Zone(ZoneNum).Name;
7184 3 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf = true;
7185 3 : if (errFlag) ErrorsFound = true;
7186 : }
7187 :
7188 2284 : if (state.dataSurface->IntMassObjects(Loop).Construction > 0) {
7189 2284 : if (state.dataConstruction->Construct(state.dataSurface->IntMassObjects(Loop).Construction).IsUsed) {
7190 2284 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConstructionStoredInputValue =
7191 2284 : state.dataSurface->IntMassObjects(Loop).Construction;
7192 : }
7193 : }
7194 2284 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea = state.dataSurface->IntMassObjects(Loop).GrossArea;
7195 2284 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea;
7196 2284 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NetAreaShadowCalc = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area;
7197 2284 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Width = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area;
7198 2284 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Height = 1.0;
7199 2284 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt = 90.0;
7200 2284 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConvOrientation =
7201 2284 : ConvectionCoefficients::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
7202 2284 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt = 0.0; // Tuned Was std::cos( 90.0 * DegToRadians )
7203 2284 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinTilt = 1.0; // Tuned Was std::sin( 90.0 * DegToRadians )
7204 2284 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth = 0.0;
7205 2284 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosAzim = 1.0; // Tuned Was std::cos( 0.0 )
7206 2284 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinAzim = 0.0; // Tuned Was std::sin( 0.0 )
7207 : // Outward normal unit vector (pointing away from room)
7208 2284 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsz;
7209 2284 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSky = 0.5;
7210 2284 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar = false;
7211 2284 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtWind = false;
7212 2284 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf = SurfNum;
7213 2284 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
7214 2284 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
7215 2284 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = UnreconciledZoneSurface;
7216 : }
7217 : }
7218 : }
7219 : }
7220 :
7221 771 : int GetNumIntMassSurfaces(EnergyPlusData &state) // Number of Internal Mass Surfaces to obtain
7222 :
7223 : {
7224 : // Counts internal mass surfaces applied to zones and zone lists
7225 :
7226 : // Using/Aliasing
7227 :
7228 : int IOStat; // IO Status when calling get input subroutine
7229 : int SurfaceNumAlpha; // Number of material alpha names being passed
7230 : int SurfaceNumArg; // Number of material properties being passed
7231 : int NumIntMassSurf; // total count of internal mass surfaces
7232 :
7233 771 : NumIntMassSurf = 0;
7234 771 : int TotIntMass = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "InternalMass");
7235 :
7236 771 : if (TotIntMass == 0) return NumIntMassSurf;
7237 164 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
7238 164 : cCurrentModuleObject = "InternalMass";
7239 : // scan for zones and zone lists in InternalMass objects
7240 2446 : for (int Item = 1; Item <= TotIntMass; ++Item) {
7241 15974 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
7242 : cCurrentModuleObject,
7243 : Item,
7244 2282 : state.dataIPShortCut->cAlphaArgs,
7245 : SurfaceNumAlpha,
7246 2282 : state.dataIPShortCut->rNumericArgs,
7247 : SurfaceNumArg,
7248 : IOStat,
7249 2282 : state.dataIPShortCut->lNumericFieldBlanks,
7250 2282 : state.dataIPShortCut->lAlphaFieldBlanks,
7251 2282 : state.dataIPShortCut->cAlphaFieldNames,
7252 2282 : state.dataIPShortCut->cNumericFieldNames);
7253 :
7254 2282 : int Item1 = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(3), state.dataHeatBal->Zone, state.dataGlobal->NumOfZones);
7255 2282 : int ZLItem = 0;
7256 2282 : if (Item1 == 0 && state.dataHeatBal->NumOfZoneLists > 0)
7257 1 : ZLItem = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(3), state.dataHeatBal->ZoneList);
7258 2282 : if (Item1 > 0) {
7259 2281 : if (state.dataIPShortCut->lAlphaFieldBlanks(4)) {
7260 2281 : ++NumIntMassSurf;
7261 : }
7262 1 : } else if (ZLItem > 0) {
7263 1 : NumIntMassSurf += state.dataHeatBal->ZoneList(ZLItem).NumOfZones;
7264 : }
7265 :
7266 2282 : if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) {
7267 0 : int Item1 = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(4), state.dataHeatBal->space);
7268 0 : int SLItem = 0;
7269 0 : if (Item1 == 0 && int(state.dataHeatBal->spaceList.size()) > 0)
7270 0 : SLItem = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(4), state.dataHeatBal->spaceList);
7271 0 : if (Item1 > 0) {
7272 0 : ++NumIntMassSurf;
7273 0 : } else if (SLItem > 0) {
7274 0 : int numOfSpaces = int(state.dataHeatBal->spaceList(SLItem).numListSpaces);
7275 0 : NumIntMassSurf += numOfSpaces;
7276 : }
7277 : }
7278 : }
7279 164 : NumIntMassSurf = max(NumIntMassSurf, TotIntMass);
7280 164 : return NumIntMassSurf;
7281 : }
7282 :
7283 9 : void GetShadingSurfReflectanceData(EnergyPlusData &state, bool &ErrorsFound) // If errors found in input
7284 : {
7285 :
7286 : // SUBROUTINE INFORMATION:
7287 : // AUTHOR Fred Winkelmann
7288 : // DATE WRITTEN Sept 2003
7289 : // MODIFIED na
7290 : // RE-ENGINEERED na
7291 :
7292 : // PURPOSE OF THIS SUBROUTINE:
7293 : // Gets data for a Shading Surface Reflectance object. This is only called when the
7294 : // Solar Distribution is to be calculated for reflectances.
7295 :
7296 : // Using/Aliasing
7297 :
7298 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
7299 :
7300 : int IOStat; // IO Status when calling get input subroutine
7301 : int NumAlpha; // Number of alpha names being passed
7302 : int NumProp; // Number of properties being passed
7303 : int TotShadingSurfaceReflectance; // Total Shading Surface Refleftance statements
7304 : int Loop; // DO loop index
7305 : int SurfNum; // Surface number
7306 : int GlConstrNum; // Glazing construction number
7307 : bool WrongSurfaceType;
7308 :
7309 : // For shading surfaces, initialize value of reflectance values to default values. These values
7310 : // may be overridden below for shading surfaces with an associated Shading Surface Reflectance object.
7311 101 : for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
7312 266 : if (!(state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Shading ||
7313 174 : state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Detached_F ||
7314 172 : state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Detached_B ||
7315 86 : state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Overhang ||
7316 86 : state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Fin))
7317 86 : continue;
7318 6 : state.dataSurface->SurfShadowDiffuseSolRefl(SurfNum) = 0.2;
7319 6 : state.dataSurface->SurfShadowDiffuseVisRefl(SurfNum) = 0.2;
7320 6 : state.dataSurface->SurfShadowGlazingFrac(SurfNum) = 0.0;
7321 6 : state.dataSurface->SurfShadowGlazingConstruct(SurfNum) = 0;
7322 : }
7323 :
7324 : // Get the total number of Shading Surface Reflectance objects
7325 9 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
7326 9 : cCurrentModuleObject = "ShadingProperty:Reflectance";
7327 9 : TotShadingSurfaceReflectance = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
7328 : // IF(TotShadingSurfaceReflectance.EQ.0) RETURN
7329 :
7330 10 : for (Loop = 1; Loop <= TotShadingSurfaceReflectance; ++Loop) {
7331 :
7332 7 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
7333 : cCurrentModuleObject,
7334 : Loop,
7335 1 : state.dataIPShortCut->cAlphaArgs,
7336 : NumAlpha,
7337 1 : state.dataIPShortCut->rNumericArgs,
7338 : NumProp,
7339 : IOStat,
7340 1 : state.dataIPShortCut->lNumericFieldBlanks,
7341 1 : state.dataIPShortCut->lAlphaFieldBlanks,
7342 1 : state.dataIPShortCut->cAlphaFieldNames,
7343 1 : state.dataIPShortCut->cNumericFieldNames);
7344 1 : SurfNum =
7345 1 : UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(1), state.dataSurface->Surface, state.dataSurface->TotSurfaces);
7346 1 : if (SurfNum == 0) {
7347 0 : ShowWarningError(state, cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", invalid specification");
7348 0 : ShowContinueError(state,
7349 0 : ".. not found " + state.dataIPShortCut->cAlphaFieldNames(1) + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\".");
7350 : // ErrorsFound =.TRUE.
7351 0 : continue;
7352 : }
7353 :
7354 : // Check that associated surface is a shading surface
7355 1 : WrongSurfaceType = false;
7356 1 : if (SurfNum != 0) {
7357 2 : if (!(state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Shading ||
7358 1 : state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Detached_F ||
7359 0 : state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Detached_B ||
7360 0 : state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Overhang ||
7361 0 : state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Fin))
7362 0 : WrongSurfaceType = true;
7363 1 : if (WrongSurfaceType) {
7364 0 : ShowSevereError(state,
7365 0 : "GetShadingSurfReflectanceData: " + cCurrentModuleObject + "=\"" + state.dataSurface->Surface(SurfNum).Name +
7366 : "\", surface is not a shading surface.");
7367 0 : ErrorsFound = true;
7368 0 : continue;
7369 : }
7370 : }
7371 :
7372 : // If associated surface is a shading surface, set reflectance values
7373 1 : state.dataSurface->SurfShadowGlazingFrac(SurfNum) = state.dataIPShortCut->rNumericArgs(3);
7374 1 : state.dataSurface->SurfShadowDiffuseSolRefl(SurfNum) =
7375 1 : (1.0 - state.dataIPShortCut->rNumericArgs(3)) * state.dataIPShortCut->rNumericArgs(1);
7376 1 : state.dataSurface->SurfShadowDiffuseVisRefl(SurfNum) =
7377 1 : (1.0 - state.dataIPShortCut->rNumericArgs(3)) * state.dataIPShortCut->rNumericArgs(2);
7378 1 : if (state.dataIPShortCut->rNumericArgs(3) > 0.0) {
7379 3 : GlConstrNum = UtilityRoutines::FindItemInList(
7380 3 : state.dataIPShortCut->cAlphaArgs(2), state.dataConstruction->Construct, state.dataHeatBal->TotConstructs);
7381 1 : if (GlConstrNum == 0) {
7382 0 : ShowSevereError(state,
7383 0 : cCurrentModuleObject + "=\"" + state.dataSurface->Surface(SurfNum).Name + "\", " +
7384 0 : state.dataIPShortCut->cAlphaFieldNames(2) + " not found=" + state.dataIPShortCut->cAlphaArgs(2));
7385 0 : ErrorsFound = true;
7386 : } else {
7387 1 : state.dataConstruction->Construct(GlConstrNum).IsUsed = true;
7388 : }
7389 1 : state.dataSurface->SurfShadowGlazingConstruct(SurfNum) = GlConstrNum;
7390 : }
7391 3 : SurfNum = UtilityRoutines::FindItemInList(
7392 4 : "Mir-" + state.dataIPShortCut->cAlphaArgs(1), state.dataSurface->Surface, state.dataSurface->TotSurfaces);
7393 1 : if (SurfNum == 0) continue;
7394 1 : state.dataSurface->SurfShadowGlazingFrac(SurfNum) = state.dataIPShortCut->rNumericArgs(3);
7395 1 : state.dataSurface->SurfShadowDiffuseSolRefl(SurfNum) =
7396 1 : (1.0 - state.dataIPShortCut->rNumericArgs(3)) * state.dataIPShortCut->rNumericArgs(1);
7397 1 : state.dataSurface->SurfShadowDiffuseVisRefl(SurfNum) =
7398 1 : (1.0 - state.dataIPShortCut->rNumericArgs(3)) * state.dataIPShortCut->rNumericArgs(2);
7399 1 : if (state.dataIPShortCut->rNumericArgs(3) > 0.0) {
7400 3 : GlConstrNum = UtilityRoutines::FindItemInList(
7401 3 : state.dataIPShortCut->cAlphaArgs(2), state.dataConstruction->Construct, state.dataHeatBal->TotConstructs);
7402 1 : if (GlConstrNum != 0) {
7403 1 : state.dataConstruction->Construct(GlConstrNum).IsUsed = true;
7404 : }
7405 1 : state.dataSurface->SurfShadowGlazingConstruct(SurfNum) = GlConstrNum;
7406 : }
7407 :
7408 : } // End of loop over Shading Surface Reflectance objects
7409 :
7410 : // Write reflectance values to .eio file.
7411 9 : print(state.files.eio,
7412 : "! <ShadingProperty Reflectance>,Shading Surface Name,Shading Type,Diffuse Solar Reflectance, Diffuse "
7413 9 : "Visible Reflectance,Surface Glazing Fraction,Surface Glazing Contruction\n");
7414 :
7415 101 : for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
7416 266 : if (!(state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Shading ||
7417 174 : state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Detached_F ||
7418 172 : state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Detached_B ||
7419 86 : state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Overhang ||
7420 86 : state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Fin))
7421 86 : continue;
7422 :
7423 6 : constexpr auto fmt{"ShadingProperty Reflectance,{},{},{:.2R},{:.2R},{:.2R}, {}\n"};
7424 6 : if (state.dataSurface->SurfShadowGlazingConstruct(SurfNum) != 0) {
7425 12 : print(state.files.eio,
7426 : fmt,
7427 2 : state.dataSurface->Surface(SurfNum).Name,
7428 4 : cSurfaceClass(state.dataSurface->Surface(SurfNum).Class),
7429 2 : state.dataSurface->SurfShadowDiffuseSolRefl(SurfNum),
7430 2 : state.dataSurface->SurfShadowDiffuseVisRefl(SurfNum),
7431 2 : state.dataSurface->SurfShadowGlazingFrac(SurfNum),
7432 4 : state.dataConstruction->Construct(state.dataSurface->SurfShadowGlazingConstruct(SurfNum)).Name);
7433 : } else {
7434 20 : print(state.files.eio,
7435 : fmt,
7436 4 : state.dataSurface->Surface(SurfNum).Name,
7437 8 : cSurfaceClass(state.dataSurface->Surface(SurfNum).Class),
7438 4 : state.dataSurface->SurfShadowDiffuseSolRefl(SurfNum),
7439 4 : state.dataSurface->SurfShadowDiffuseVisRefl(SurfNum),
7440 4 : state.dataSurface->SurfShadowGlazingFrac(SurfNum),
7441 4 : "N/A");
7442 : }
7443 : }
7444 9 : }
7445 :
7446 771 : void GetHTSurfExtVentedCavityData(EnergyPlusData &state, bool &ErrorsFound) // Error flag indicator (true if errors found)
7447 : {
7448 :
7449 : // SUBROUTINE INFORMATION:
7450 : // AUTHOR BGriffith
7451 : // DATE WRITTEN January 2005
7452 : // MODIFIED na
7453 : // RE-ENGINEERED na
7454 :
7455 : // PURPOSE OF THIS SUBROUTINE:
7456 : // load input data for Exterior Vented Cavity Special case for heat transfer surfaces
7457 :
7458 : // METHODOLOGY EMPLOYED:
7459 : // usual E+ input processes
7460 :
7461 : // REFERENCES:
7462 : // derived from SUBROUTINE GetTranspiredCollectorInput
7463 :
7464 : // Using/Aliasing
7465 :
7466 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
7467 :
7468 : int Item; // Item to be "gotten"
7469 : int NumAlphas; // Number of Alphas for each GetObjectItem call
7470 : int NumNumbers; // Number of Numbers for each GetObjectItem call
7471 : int MaxNumAlphas; // argument for call to GetObjectDefMaxArgs
7472 : int MaxNumNumbers; // argument for call to GetObjectDefMaxArgs
7473 : int Dummy; // argument for call to GetObjectDefMaxArgs
7474 : int IOStatus; // Used in GetObjectItem
7475 : int Found;
7476 : int AlphaOffset; // local temp var
7477 1542 : std::string Roughness;
7478 : int ThisSurf; // do loop counter
7479 : Real64 AvgAzimuth; // temp for error checking
7480 : Real64 AvgTilt; // temp for error checking
7481 : int SurfID; // local surface "pointer"
7482 : bool IsBlank;
7483 : bool ErrorInName;
7484 771 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
7485 771 : cCurrentModuleObject = "SurfaceProperty:ExteriorNaturalVentedCavity";
7486 771 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, Dummy, MaxNumAlphas, MaxNumNumbers);
7487 :
7488 771 : if (MaxNumNumbers != 8) {
7489 0 : ShowSevereError(
7490 0 : state, format("{}: Object Definition indicates not = 8 Number Objects, Number Indicated={}", cCurrentModuleObject, MaxNumNumbers));
7491 0 : ErrorsFound = true;
7492 : }
7493 :
7494 771 : state.dataSurface->TotExtVentCav = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
7495 :
7496 771 : state.dataSurface->ExtVentedCavity.allocate(state.dataSurface->TotExtVentCav);
7497 :
7498 776 : for (Item = 1; Item <= state.dataSurface->TotExtVentCav; ++Item) {
7499 35 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
7500 : cCurrentModuleObject,
7501 : Item,
7502 5 : state.dataIPShortCut->cAlphaArgs,
7503 : NumAlphas,
7504 5 : state.dataIPShortCut->rNumericArgs,
7505 : NumNumbers,
7506 : IOStatus,
7507 5 : state.dataIPShortCut->lNumericFieldBlanks,
7508 5 : state.dataIPShortCut->lAlphaFieldBlanks,
7509 5 : state.dataIPShortCut->cAlphaFieldNames,
7510 5 : state.dataIPShortCut->cNumericFieldNames);
7511 : // first handle cAlphaArgs
7512 5 : ErrorInName = false;
7513 5 : IsBlank = false;
7514 :
7515 15 : UtilityRoutines::VerifyName(state,
7516 5 : state.dataIPShortCut->cAlphaArgs(1),
7517 5 : state.dataSurface->ExtVentedCavity,
7518 : Item - 1,
7519 : ErrorInName,
7520 : IsBlank,
7521 10 : cCurrentModuleObject + " Name");
7522 5 : if (ErrorInName) {
7523 0 : ShowContinueError(state, "...cannot not duplicate other names");
7524 0 : ErrorsFound = true;
7525 0 : continue;
7526 : }
7527 5 : state.dataSurface->ExtVentedCavity(Item).Name = state.dataIPShortCut->cAlphaArgs(1);
7528 :
7529 5 : state.dataSurface->ExtVentedCavity(Item).OSCMName = state.dataIPShortCut->cAlphaArgs(2);
7530 5 : if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) {
7531 15 : Found = UtilityRoutines::FindItemInList(
7532 15 : state.dataSurface->ExtVentedCavity(Item).OSCMName, state.dataSurface->OSCM, state.dataSurface->TotOSCM);
7533 5 : if (Found == 0) {
7534 0 : ShowSevereError(state,
7535 0 : cCurrentModuleObject + "=\"" + state.dataSurface->ExtVentedCavity(Item).Name + "\", invalid " +
7536 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) + "\".");
7537 0 : ErrorsFound = true;
7538 : }
7539 : } else {
7540 0 : Found = 0;
7541 0 : ShowSevereError(state,
7542 0 : cCurrentModuleObject + "=\"" + state.dataSurface->ExtVentedCavity(Item).Name + "\", invalid " +
7543 0 : state.dataIPShortCut->cAlphaFieldNames(2) + " cannot be blank.");
7544 0 : ErrorsFound = true;
7545 : }
7546 5 : state.dataSurface->ExtVentedCavity(Item).OSCMPtr = Found;
7547 :
7548 5 : Roughness = state.dataIPShortCut->cAlphaArgs(3);
7549 : // Select the correct Number for the associated ascii name for the roughness type
7550 5 : if (UtilityRoutines::SameString(Roughness, "VerySmooth")) {
7551 0 : state.dataSurface->ExtVentedCavity(Item).BaffleRoughness = DataSurfaces::SurfaceRoughness::VerySmooth;
7552 5 : } else if (UtilityRoutines::SameString(Roughness, "Smooth")) {
7553 5 : state.dataSurface->ExtVentedCavity(Item).BaffleRoughness = DataSurfaces::SurfaceRoughness::Smooth;
7554 0 : } else if (UtilityRoutines::SameString(Roughness, "MediumSmooth")) {
7555 0 : state.dataSurface->ExtVentedCavity(Item).BaffleRoughness = DataSurfaces::SurfaceRoughness::MediumSmooth;
7556 0 : } else if (UtilityRoutines::SameString(Roughness, "MediumRough")) {
7557 0 : state.dataSurface->ExtVentedCavity(Item).BaffleRoughness = DataSurfaces::SurfaceRoughness::MediumRough;
7558 0 : } else if (UtilityRoutines::SameString(Roughness, "Rough")) {
7559 0 : state.dataSurface->ExtVentedCavity(Item).BaffleRoughness = DataSurfaces::SurfaceRoughness::Rough;
7560 0 : } else if (UtilityRoutines::SameString(Roughness, "VeryRough")) {
7561 0 : state.dataSurface->ExtVentedCavity(Item).BaffleRoughness = DataSurfaces::SurfaceRoughness::VeryRough;
7562 : } // TODO: fix this after creating FindEnumeratedValueIndex()
7563 :
7564 : // Was it set?
7565 5 : if (state.dataSurface->ExtVentedCavity(Item).BaffleRoughness == DataSurfaces::SurfaceRoughness::Invalid) {
7566 0 : ShowSevereError(state,
7567 0 : cCurrentModuleObject + "=\"" + state.dataSurface->ExtVentedCavity(Item).Name + "\", invalid " +
7568 0 : state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3));
7569 0 : ErrorsFound = true;
7570 : }
7571 :
7572 5 : AlphaOffset = 3;
7573 5 : state.dataSurface->ExtVentedCavity(Item).NumSurfs = NumAlphas - AlphaOffset;
7574 5 : if (state.dataSurface->ExtVentedCavity(Item).NumSurfs == 0) {
7575 0 : ShowSevereError(state,
7576 0 : cCurrentModuleObject + "=\"" + state.dataSurface->ExtVentedCavity(Item).Name +
7577 : "\", no underlying surfaces specified. Must have at least one.");
7578 0 : ErrorsFound = true;
7579 0 : continue;
7580 : }
7581 5 : state.dataSurface->ExtVentedCavity(Item).SurfPtrs.allocate(state.dataSurface->ExtVentedCavity(Item).NumSurfs);
7582 5 : state.dataSurface->ExtVentedCavity(Item).SurfPtrs = 0;
7583 10 : for (ThisSurf = 1; ThisSurf <= state.dataSurface->ExtVentedCavity(Item).NumSurfs; ++ThisSurf) {
7584 15 : Found = UtilityRoutines::FindItemInList(
7585 15 : state.dataIPShortCut->cAlphaArgs(ThisSurf + AlphaOffset), state.dataSurface->Surface, state.dataSurface->TotSurfaces);
7586 5 : if (Found == 0) {
7587 0 : ShowSevereError(state,
7588 0 : cCurrentModuleObject + "=\"" + state.dataSurface->ExtVentedCavity(Item).Name + "\", invalid " +
7589 0 : state.dataIPShortCut->cAlphaFieldNames(ThisSurf + AlphaOffset) + "=\"" +
7590 0 : state.dataIPShortCut->cAlphaArgs(ThisSurf + AlphaOffset));
7591 0 : ErrorsFound = true;
7592 0 : continue;
7593 : }
7594 : // check that surface is appropriate, Heat transfer, Sun, Wind,
7595 5 : if (!state.dataSurface->Surface(Found).HeatTransSurf) {
7596 0 : ShowSevereError(state,
7597 0 : cCurrentModuleObject + "=\"" + state.dataSurface->ExtVentedCavity(Item).Name + "\", invalid " +
7598 0 : state.dataIPShortCut->cAlphaFieldNames(ThisSurf + AlphaOffset) + "=\"" +
7599 0 : state.dataIPShortCut->cAlphaArgs(ThisSurf + AlphaOffset));
7600 0 : ShowContinueError(state, "...because it is not a Heat Transfer Surface.");
7601 0 : ErrorsFound = true;
7602 0 : continue;
7603 : }
7604 5 : if (!state.dataSurface->Surface(Found).ExtSolar) {
7605 0 : ShowSevereError(state,
7606 0 : cCurrentModuleObject + "=\"" + state.dataSurface->ExtVentedCavity(Item).Name + "\", invalid " +
7607 0 : state.dataIPShortCut->cAlphaFieldNames(ThisSurf + AlphaOffset) + "=\"" +
7608 0 : state.dataIPShortCut->cAlphaArgs(ThisSurf + AlphaOffset));
7609 0 : ShowContinueError(state, "...because it is not exposed to Sun.");
7610 0 : ErrorsFound = true;
7611 0 : continue;
7612 : }
7613 5 : if (!state.dataSurface->Surface(Found).ExtWind) {
7614 0 : ShowSevereError(state,
7615 0 : cCurrentModuleObject + "=\"" + state.dataSurface->ExtVentedCavity(Item).Name + "\", invalid " +
7616 0 : state.dataIPShortCut->cAlphaFieldNames(ThisSurf + AlphaOffset) + "=\"" +
7617 0 : state.dataIPShortCut->cAlphaArgs(ThisSurf + AlphaOffset));
7618 0 : ShowContinueError(state, "...because it is not exposed to Wind.");
7619 0 : ErrorsFound = true;
7620 0 : continue;
7621 : }
7622 5 : if (state.dataSurface->Surface(Found).ExtBoundCond != OtherSideCondModeledExt) {
7623 0 : ShowSevereError(state, cCurrentModuleObject + "=\"" + state.dataSurface->ExtVentedCavity(Item).Name + "\", is invalid");
7624 0 : ShowContinueError(state,
7625 0 : "...because " + state.dataIPShortCut->cAlphaFieldNames(ThisSurf + AlphaOffset) + "=\"" +
7626 0 : state.dataIPShortCut->cAlphaArgs(ThisSurf + AlphaOffset) + "\".");
7627 0 : ShowContinueError(state, "...is not an OtherSideConditionedModel surface.");
7628 0 : ErrorsFound = true;
7629 0 : continue;
7630 : }
7631 5 : state.dataSurface->ExtVentedCavity(Item).SurfPtrs(ThisSurf) = Found;
7632 :
7633 : // now set info in Surface structure
7634 5 : state.dataSurface->SurfExtCavNum(Found) = Item;
7635 5 : state.dataSurface->SurfExtCavityPresent(Found) = true;
7636 : }
7637 :
7638 5 : if (ErrorsFound) continue; // previous inner do loop may have detected problems that need to be cycle'd again to avoid crash
7639 :
7640 : // now that we should have all the surfaces, do some preperations and checks.
7641 :
7642 : // are they all similar tilt and azimuth? Issue warnings so people can do it if they really want
7643 5 : Real64 const surfaceArea(sum_sub(state.dataSurface->Surface, &SurfaceData::Area, state.dataSurface->ExtVentedCavity(Item).SurfPtrs));
7644 : // AvgAzimuth = sum( Surface( ExtVentedCavity( Item ).SurfPtrs ).Azimuth * Surface( ExtVentedCavity( Item ).SurfPtrs
7645 : //).Area
7646 : //)
7647 : /// sum( Surface( ExtVentedCavity( Item ).SurfPtrs ).Area ); //Autodesk:F2C++ Array subscript usage: Replaced by below
7648 5 : AvgAzimuth = sum_product_sub(state.dataSurface->Surface,
7649 : &SurfaceData::Azimuth,
7650 : &SurfaceData::Area,
7651 5 : state.dataSurface->ExtVentedCavity(Item).SurfPtrs) /
7652 : surfaceArea; // Autodesk:F2C++ Functions handle array subscript usage
7653 : // AvgTilt = sum( Surface( ExtVentedCavity( Item ).SurfPtrs ).Tilt * Surface( ExtVentedCavity( Item ).SurfPtrs ).Area )
7654 : // /
7655 : // sum( Surface( ExtVentedCavity( Item ).SurfPtrs ).Area ); //Autodesk:F2C++ Array subscript usage: Replaced by below
7656 10 : AvgTilt = sum_product_sub(
7657 10 : state.dataSurface->Surface, &SurfaceData::Tilt, &SurfaceData::Area, state.dataSurface->ExtVentedCavity(Item).SurfPtrs) /
7658 : surfaceArea; // Autodesk:F2C++ Functions handle array subscript usage
7659 10 : for (ThisSurf = 1; ThisSurf <= state.dataSurface->ExtVentedCavity(Item).NumSurfs; ++ThisSurf) {
7660 5 : SurfID = state.dataSurface->ExtVentedCavity(Item).SurfPtrs(ThisSurf);
7661 5 : if (std::abs(state.dataSurface->Surface(SurfID).Azimuth - AvgAzimuth) > 15.0) {
7662 0 : ShowWarningError(state,
7663 0 : cCurrentModuleObject + "=\"" + state.dataSurface->ExtVentedCavity(Item).Name + ", Surface " +
7664 0 : state.dataSurface->Surface(SurfID).Name + " has Azimuth different from others in the associated group.");
7665 : }
7666 5 : if (std::abs(state.dataSurface->Surface(SurfID).Tilt - AvgTilt) > 10.0) {
7667 0 : ShowWarningError(state,
7668 0 : cCurrentModuleObject + "=\"" + state.dataSurface->ExtVentedCavity(Item).Name + ", Surface " +
7669 0 : state.dataSurface->Surface(SurfID).Name + " has Tilt different from others in the associated group.");
7670 : }
7671 :
7672 : // test that there are no windows. Now allow windows
7673 : // If (Surface(SurfID)%GrossArea > Surface(SurfID)%Area) Then
7674 : // Call ShowWarningError(state, 'Surface '//TRIM(Surface(SurfID)%name)//' has a subsurface whose area is not being ' &
7675 : // //'subtracted in the group of surfaces associated with '//TRIM(ExtVentedCavity(Item)%Name))
7676 : // endif
7677 : }
7678 5 : state.dataSurface->ExtVentedCavity(Item).Tilt = AvgTilt;
7679 5 : state.dataSurface->ExtVentedCavity(Item).Azimuth = AvgAzimuth;
7680 :
7681 : // find area weighted centroid.
7682 : // ExtVentedCavity( Item ).Centroid.z = sum( Surface( ExtVentedCavity( Item ).SurfPtrs ).Centroid.z * Surface(
7683 : // ExtVentedCavity( Item
7684 : //).SurfPtrs ).Area ) / sum( Surface( ExtVentedCavity( Item ).SurfPtrs ).Area ); //Autodesk:F2C++ Array subscript usage: Replaced
7685 : // by below
7686 15 : state.dataSurface->ExtVentedCavity(Item).Centroid.z = sum_product_sub(state.dataSurface->Surface,
7687 : &SurfaceData::Centroid,
7688 : &Vector::z,
7689 5 : state.dataSurface->Surface,
7690 : &SurfaceData::Area,
7691 10 : state.dataSurface->ExtVentedCavity(Item).SurfPtrs) /
7692 : surfaceArea; // Autodesk:F2C++ Functions handle array subscript usage
7693 :
7694 : // now handle rNumericArgs from input object
7695 5 : state.dataSurface->ExtVentedCavity(Item).Porosity = state.dataIPShortCut->rNumericArgs(1);
7696 5 : state.dataSurface->ExtVentedCavity(Item).LWEmitt = state.dataIPShortCut->rNumericArgs(2);
7697 5 : state.dataSurface->ExtVentedCavity(Item).SolAbsorp = state.dataIPShortCut->rNumericArgs(3);
7698 5 : state.dataSurface->ExtVentedCavity(Item).HdeltaNPL = state.dataIPShortCut->rNumericArgs(4);
7699 5 : state.dataSurface->ExtVentedCavity(Item).PlenGapThick = state.dataIPShortCut->rNumericArgs(5);
7700 5 : if (state.dataSurface->ExtVentedCavity(Item).PlenGapThick <= 0.0) {
7701 0 : ShowSevereError(state, cCurrentModuleObject + "=\"" + state.dataSurface->ExtVentedCavity(Item).Name + "\", invalid .");
7702 0 : ErrorsFound = true;
7703 0 : ShowContinueError(state,
7704 0 : format("...because field \"{}\" must be greater than Zero=[{:.2T}].",
7705 0 : state.dataIPShortCut->cNumericFieldNames(5),
7706 0 : state.dataIPShortCut->rNumericArgs(5)));
7707 0 : continue;
7708 : }
7709 5 : state.dataSurface->ExtVentedCavity(Item).AreaRatio = state.dataIPShortCut->rNumericArgs(6);
7710 5 : state.dataSurface->ExtVentedCavity(Item).Cv = state.dataIPShortCut->rNumericArgs(7);
7711 5 : state.dataSurface->ExtVentedCavity(Item).Cd = state.dataIPShortCut->rNumericArgs(8);
7712 :
7713 : // Fill out data we now know
7714 : // sum areas of HT surface areas
7715 : // ExtVentedCavity( Item ).ProjArea = sum( Surface( ExtVentedCavity( Item ).SurfPtrs ).Area ); //Autodesk:F2C++ Array
7716 : // subscript usage: Replaced by below
7717 5 : state.dataSurface->ExtVentedCavity(Item).ProjArea = surfaceArea;
7718 5 : if (state.dataSurface->ExtVentedCavity(Item).ProjArea <= 0.0) {
7719 0 : ShowSevereError(state, cCurrentModuleObject + "=\"" + state.dataSurface->ExtVentedCavity(Item).Name + "\", invalid .");
7720 0 : ErrorsFound = true;
7721 0 : ShowContinueError(state,
7722 0 : format("...because gross area of underlying surfaces must be greater than Zero=[{:.2T}].",
7723 0 : state.dataSurface->ExtVentedCavity(Item).ProjArea));
7724 0 : continue;
7725 : }
7726 5 : state.dataSurface->ExtVentedCavity(Item).ActualArea =
7727 5 : state.dataSurface->ExtVentedCavity(Item).ProjArea * state.dataSurface->ExtVentedCavity(Item).AreaRatio;
7728 :
7729 20 : SetupOutputVariable(state,
7730 : "Surface Exterior Cavity Baffle Surface Temperature",
7731 : OutputProcessor::Unit::C,
7732 5 : state.dataSurface->ExtVentedCavity(Item).Tbaffle,
7733 : OutputProcessor::SOVTimeStepType::System,
7734 : OutputProcessor::SOVStoreType::Average,
7735 10 : state.dataSurface->ExtVentedCavity(Item).Name);
7736 20 : SetupOutputVariable(state,
7737 : "Surface Exterior Cavity Air Drybulb Temperature",
7738 : OutputProcessor::Unit::C,
7739 5 : state.dataSurface->ExtVentedCavity(Item).TAirCav,
7740 : OutputProcessor::SOVTimeStepType::System,
7741 : OutputProcessor::SOVStoreType::Average,
7742 10 : state.dataSurface->ExtVentedCavity(Item).Name);
7743 20 : SetupOutputVariable(state,
7744 : "Surface Exterior Cavity Total Natural Ventilation Air Change Rate",
7745 : OutputProcessor::Unit::ach,
7746 5 : state.dataSurface->ExtVentedCavity(Item).PassiveACH,
7747 : OutputProcessor::SOVTimeStepType::System,
7748 : OutputProcessor::SOVStoreType::Average,
7749 10 : state.dataSurface->ExtVentedCavity(Item).Name);
7750 20 : SetupOutputVariable(state,
7751 : "Surface Exterior Cavity Total Natural Ventilation Mass Flow Rate",
7752 : OutputProcessor::Unit::kg_s,
7753 5 : state.dataSurface->ExtVentedCavity(Item).PassiveMdotVent,
7754 : OutputProcessor::SOVTimeStepType::System,
7755 : OutputProcessor::SOVStoreType::Average,
7756 10 : state.dataSurface->ExtVentedCavity(Item).Name);
7757 20 : SetupOutputVariable(state,
7758 : "Surface Exterior Cavity Natural Ventilation from Wind Mass Flow Rate",
7759 : OutputProcessor::Unit::kg_s,
7760 5 : state.dataSurface->ExtVentedCavity(Item).PassiveMdotWind,
7761 : OutputProcessor::SOVTimeStepType::System,
7762 : OutputProcessor::SOVStoreType::Average,
7763 10 : state.dataSurface->ExtVentedCavity(Item).Name);
7764 20 : SetupOutputVariable(state,
7765 : "Surface Exterior Cavity Natural Ventilation from Buoyancy Mass Flow Rate",
7766 : OutputProcessor::Unit::kg_s,
7767 5 : state.dataSurface->ExtVentedCavity(Item).PassiveMdotTherm,
7768 : OutputProcessor::SOVTimeStepType::System,
7769 : OutputProcessor::SOVStoreType::Average,
7770 10 : state.dataSurface->ExtVentedCavity(Item).Name);
7771 : }
7772 771 : }
7773 :
7774 771 : void ExposedFoundationPerimeter::getData(EnergyPlusData &state, bool &ErrorsFound)
7775 : {
7776 :
7777 : int IOStatus; // Used in GetObjectItem
7778 : int NumAlphas;
7779 : int NumNumbers;
7780 :
7781 771 : auto const tolerance = 1e-6;
7782 :
7783 1542 : std::string cCurrentModuleObject = "SurfaceProperty:ExposedFoundationPerimeter";
7784 771 : int numObjects = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
7785 :
7786 794 : for (int obj = 1; obj <= numObjects; ++obj) {
7787 23 : int alpF = 1;
7788 23 : int numF = 1;
7789 161 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
7790 : cCurrentModuleObject,
7791 : obj,
7792 23 : state.dataIPShortCut->cAlphaArgs,
7793 : NumAlphas,
7794 23 : state.dataIPShortCut->rNumericArgs,
7795 : NumNumbers,
7796 : IOStatus,
7797 23 : state.dataIPShortCut->lNumericFieldBlanks,
7798 23 : state.dataIPShortCut->lAlphaFieldBlanks,
7799 23 : state.dataIPShortCut->cAlphaFieldNames,
7800 23 : state.dataIPShortCut->cNumericFieldNames);
7801 : int Found =
7802 23 : UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(alpF), state.dataSurface->Surface, state.dataSurface->TotSurfaces);
7803 23 : if (Found == 0) {
7804 0 : ShowSevereError(state, cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", did not find matching surface");
7805 0 : ErrorsFound = true;
7806 : }
7807 23 : alpF++;
7808 23 : if (state.dataSurface->Surface(Found).Class != SurfaceClass::Floor) {
7809 0 : ShowWarningError(state, cCurrentModuleObject + ": " + state.dataSurface->Surface(Found).Name + ", surface is not a floor surface");
7810 0 : ShowContinueError(state, cCurrentModuleObject + " will not be used");
7811 0 : continue;
7812 : }
7813 :
7814 : // Choose calculation method
7815 46 : std::string calculationMethod = state.dataIPShortCut->cAlphaArgs(alpF);
7816 23 : if (calculationMethod != "TOTALEXPOSEDPERIMETER" && calculationMethod != "EXPOSEDPERIMETERFRACTION" && calculationMethod != "BYSEGMENT") {
7817 0 : ShowSevereError(state,
7818 0 : cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", " + calculationMethod +
7819 0 : " is not a valid choice for " + state.dataIPShortCut->cAlphaFieldNames(alpF));
7820 0 : ErrorsFound = true;
7821 : }
7822 23 : alpF++;
7823 :
7824 46 : Data data;
7825 23 : data.useDetailedExposedPerimeter = true;
7826 :
7827 23 : if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
7828 1 : if (calculationMethod == "TOTALEXPOSEDPERIMETER") {
7829 1 : data.exposedFraction = state.dataIPShortCut->rNumericArgs(numF) / state.dataSurface->Surface(Found).Perimeter;
7830 1 : if (data.exposedFraction > 1 + tolerance) {
7831 0 : ShowWarningError(state,
7832 0 : cCurrentModuleObject + ": " + state.dataSurface->Surface(Found).Name + ", " +
7833 0 : state.dataIPShortCut->cNumericFieldNames(numF) + " is greater than the perimeter of " +
7834 0 : state.dataSurface->Surface(Found).Name);
7835 0 : ShowContinueError(state,
7836 0 : format("{} perimeter = {}, {} exposed perimeter = {}",
7837 0 : state.dataSurface->Surface(Found).Name,
7838 0 : state.dataSurface->Surface(Found).Perimeter,
7839 : cCurrentModuleObject,
7840 0 : state.dataIPShortCut->rNumericArgs(numF)));
7841 0 : ShowContinueError(state,
7842 0 : state.dataIPShortCut->cNumericFieldNames(numF) + " will be set equal to " +
7843 0 : state.dataSurface->Surface(Found).Name + " perimeter");
7844 0 : data.exposedFraction = 1.0;
7845 : }
7846 :
7847 1 : data.useDetailedExposedPerimeter = false;
7848 : } else {
7849 0 : ShowWarningError(state,
7850 0 : cCurrentModuleObject + ": " + state.dataSurface->Surface(Found).Name + ", " + calculationMethod +
7851 0 : " set as calculation method, but a value has been set for " +
7852 0 : state.dataIPShortCut->cNumericFieldNames(numF) + ". This value will be ignored.");
7853 : }
7854 : } else {
7855 22 : if (calculationMethod == "TOTALEXPOSEDPERIMETER") {
7856 0 : ShowSevereError(state,
7857 0 : cCurrentModuleObject + ": " + state.dataSurface->Surface(Found).Name + ", " + calculationMethod +
7858 0 : " set as calculation method, but no value has been set for " +
7859 0 : state.dataIPShortCut->cNumericFieldNames(numF));
7860 0 : ErrorsFound = true;
7861 : }
7862 : }
7863 23 : numF++;
7864 :
7865 23 : if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
7866 3 : if (calculationMethod == "EXPOSEDPERIMETERFRACTION") {
7867 3 : data.exposedFraction = state.dataIPShortCut->rNumericArgs(numF);
7868 3 : data.useDetailedExposedPerimeter = false;
7869 : } else {
7870 0 : ShowWarningError(state,
7871 0 : cCurrentModuleObject + ": " + state.dataSurface->Surface(Found).Name + ", " + calculationMethod +
7872 0 : " set as calculation method, but a value has been set for " +
7873 0 : state.dataIPShortCut->cNumericFieldNames(numF) + ". This value will be ignored.");
7874 : }
7875 : } else {
7876 20 : if (calculationMethod == "EXPOSEDPERIMETERFRACTION") {
7877 0 : ShowSevereError(state,
7878 0 : cCurrentModuleObject + ": " + state.dataSurface->Surface(Found).Name + ", " + calculationMethod +
7879 0 : " set as calculation method, but no value has been set for " +
7880 0 : state.dataIPShortCut->cNumericFieldNames(numF));
7881 0 : ErrorsFound = true;
7882 : }
7883 : }
7884 23 : numF++;
7885 :
7886 23 : int numRemainingFields = NumAlphas - (alpF - 1) + NumNumbers - (numF - 1);
7887 23 : if (numRemainingFields > 0) {
7888 19 : if (calculationMethod == "BYSEGMENT") {
7889 19 : if (numRemainingFields != (int)state.dataSurface->Surface(Found).Vertex.size()) {
7890 0 : ShowSevereError(state,
7891 0 : cCurrentModuleObject + ": " + state.dataSurface->Surface(Found).Name +
7892 0 : ", must have equal number of segments as the floor has vertices." +
7893 0 : state.dataIPShortCut->cAlphaFieldNames(alpF) + "\" and \"" +
7894 0 : state.dataIPShortCut->cNumericFieldNames(numF - 1) + "\"");
7895 0 : ShowContinueError(state,
7896 0 : format("{} number of vertices = {}, {} number of segments = {}",
7897 0 : state.dataSurface->Surface(Found).Name,
7898 0 : state.dataSurface->Surface(Found).Vertex.size(),
7899 : cCurrentModuleObject,
7900 0 : numRemainingFields));
7901 0 : ErrorsFound = true;
7902 : }
7903 95 : for (int segNum = 0; segNum < numRemainingFields; segNum++) {
7904 76 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(alpF), "YES")) {
7905 28 : data.isExposedPerimeter.push_back(true);
7906 48 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(alpF), "NO")) {
7907 48 : data.isExposedPerimeter.push_back(false);
7908 0 : } else if (state.dataIPShortCut->lAlphaFieldBlanks(alpF)) {
7909 0 : ShowSevereError(state,
7910 0 : cCurrentModuleObject + ": " + state.dataSurface->Surface(Found).Name + ", " + calculationMethod +
7911 0 : " set as calculation method, but no value has been set for " +
7912 0 : state.dataIPShortCut->cAlphaFieldNames(alpF) + ". Must be \"Yes\" or \"No\".");
7913 0 : ErrorsFound = true;
7914 : } else {
7915 0 : ShowSevereError(state,
7916 0 : cCurrentModuleObject + ": " + state.dataSurface->Surface(Found).Name + ", " +
7917 0 : state.dataIPShortCut->cAlphaFieldNames(alpF) + " invalid [" + state.dataIPShortCut->cAlphaArgs(alpF) +
7918 : "]. Must be \"Yes\" or \"No\".");
7919 0 : ErrorsFound = true;
7920 : }
7921 76 : alpF++;
7922 : }
7923 : }
7924 : } else {
7925 4 : if (calculationMethod == "BYSEGMENT") {
7926 0 : ShowSevereError(state,
7927 0 : cCurrentModuleObject + ": " + state.dataSurface->Surface(Found).Name + ", " + calculationMethod +
7928 : " set as calculation method, but no values have been set for Surface Segments Exposed");
7929 0 : ErrorsFound = true;
7930 : }
7931 : }
7932 23 : surfaceMap[Found] = data;
7933 : }
7934 771 : }
7935 :
7936 771 : void GetSurfaceLocalEnvData(EnergyPlusData &state, bool &ErrorsFound) // Error flag indicator (true if errors found)
7937 : {
7938 : // SUBROUTINE INFORMATION:
7939 : // AUTHOR X LUO
7940 : // DATE WRITTEN July 2017
7941 : // MODIFIED na
7942 : // RE-ENGINEERED na
7943 :
7944 : // PURPOSE OF THIS SUBROUTINE:
7945 : // load input data for Outdoor Air Node for exterior surfaces
7946 :
7947 : // Using/Aliasing
7948 : using namespace DataErrorTracking;
7949 : using DataLoopNode::ObjectIsParent;
7950 : using NodeInputManager::GetOnlySingleNode;
7951 : using OutAirNodeManager::CheckOutAirNodeNumber;
7952 : using ScheduleManager::GetScheduleIndex;
7953 :
7954 : // SUBROUTINE PARAMETER DEFINITIONS:
7955 : static constexpr std::string_view RoutineName("GetSurfaceLocalEnvData: ");
7956 :
7957 : // INTERFACE BLOCK SPECIFICATIONS:na
7958 : // DERIVED TYPE DEFINITIONS:na
7959 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
7960 : int NumAlpha;
7961 : int NumNumeric;
7962 : int IOStat;
7963 :
7964 : //-----------------------------------------------------------------------
7965 : // SurfaceProperty:LocalEnvironment
7966 : //-----------------------------------------------------------------------
7967 771 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
7968 771 : cCurrentModuleObject = "SurfaceProperty:LocalEnvironment";
7969 771 : state.dataSurface->TotSurfLocalEnv = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
7970 :
7971 771 : if (state.dataSurface->TotSurfLocalEnv > 0) {
7972 :
7973 4 : state.dataGlobal->AnyLocalEnvironmentsInModel = true;
7974 :
7975 4 : if (!allocated(state.dataSurface->SurfLocalEnvironment)) {
7976 4 : state.dataSurface->SurfLocalEnvironment.allocate(state.dataSurface->TotSurfLocalEnv);
7977 : }
7978 :
7979 126 : for (int Loop = 1; Loop <= state.dataSurface->TotSurfLocalEnv; ++Loop) {
7980 :
7981 122 : auto &SurfLocalEnv = state.dataSurface->SurfLocalEnvironment(Loop);
7982 :
7983 854 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
7984 : cCurrentModuleObject,
7985 : Loop,
7986 122 : state.dataIPShortCut->cAlphaArgs,
7987 : NumAlpha,
7988 122 : state.dataIPShortCut->rNumericArgs,
7989 : NumNumeric,
7990 : IOStat,
7991 122 : state.dataIPShortCut->lNumericFieldBlanks,
7992 122 : state.dataIPShortCut->lAlphaFieldBlanks,
7993 122 : state.dataIPShortCut->cAlphaFieldNames,
7994 122 : state.dataIPShortCut->cNumericFieldNames);
7995 122 : UtilityRoutines::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
7996 :
7997 122 : SurfLocalEnv.Name = state.dataIPShortCut->cAlphaArgs(1);
7998 :
7999 : // Assign surface number
8000 122 : int SurfNum = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(2), state.dataSurface->Surface);
8001 122 : if (SurfNum == 0) {
8002 0 : ShowSevereError(state,
8003 0 : format("{} {} = \"{}\", object. Illegal value for \"{}\" has been found.",
8004 : RoutineName,
8005 : cCurrentModuleObject,
8006 : SurfLocalEnv.Name,
8007 0 : state.dataIPShortCut->cAlphaFieldNames(2)));
8008 0 : ShowContinueError(state,
8009 0 : format("{} entered value = \"{}\", no corresponding surface (ref BuildingSurface:Detailed) has been "
8010 : "found in the input file.",
8011 0 : state.dataIPShortCut->cAlphaFieldNames(2),
8012 0 : state.dataIPShortCut->cAlphaArgs(2)));
8013 0 : ErrorsFound = true;
8014 : } else {
8015 122 : SurfLocalEnv.SurfPtr = SurfNum;
8016 : }
8017 :
8018 : // Assign External Shading Schedule number
8019 122 : if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) {
8020 102 : int ExtShadingSchedNum = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(3));
8021 102 : if (ExtShadingSchedNum == 0) {
8022 0 : ShowSevereError(state,
8023 0 : format("{} {} = \"{}\", object. Illegal value for \"{}\" has been found.",
8024 : RoutineName,
8025 : cCurrentModuleObject,
8026 : SurfLocalEnv.Name,
8027 0 : state.dataIPShortCut->cAlphaFieldNames(3)));
8028 0 : ShowContinueError(state,
8029 0 : format("{} entered value = \"{}\", no corresponding shading schedule has been found in the input file.",
8030 0 : state.dataIPShortCut->cAlphaFieldNames(3),
8031 0 : state.dataIPShortCut->cAlphaArgs(3)));
8032 0 : ErrorsFound = true;
8033 : } else {
8034 102 : SurfLocalEnv.ExtShadingSchedPtr = ExtShadingSchedNum;
8035 : }
8036 : }
8037 :
8038 : // Assign surrounding surfaces object number;
8039 122 : if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) {
8040 : int SurroundingSurfsNum =
8041 6 : UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(4), state.dataSurface->SurroundingSurfsProperty);
8042 6 : if (SurroundingSurfsNum == 0) {
8043 0 : ShowSevereError(state,
8044 0 : format("{} {} = \"{}\", object. Illegal value for \"{}\" has been found.",
8045 : RoutineName,
8046 : cCurrentModuleObject,
8047 : SurfLocalEnv.Name,
8048 0 : state.dataIPShortCut->cAlphaFieldNames(4)));
8049 0 : ShowContinueError(state,
8050 0 : format("{} entered value = \"{}\", no corresponding surrounding surfaces properties has been found "
8051 : "in the input file.",
8052 0 : state.dataIPShortCut->cAlphaFieldNames(4),
8053 0 : state.dataIPShortCut->cAlphaArgs(4)));
8054 0 : ErrorsFound = true;
8055 : } else {
8056 6 : SurfLocalEnv.SurroundingSurfsPtr = SurroundingSurfsNum;
8057 : }
8058 : }
8059 :
8060 : // Assign outdoor air node number;
8061 122 : if (!state.dataIPShortCut->lAlphaFieldBlanks(5)) {
8062 4 : int NodeNum = GetOnlySingleNode(state,
8063 2 : state.dataIPShortCut->cAlphaArgs(5),
8064 : ErrorsFound,
8065 : DataLoopNode::ConnectionObjectType::SurfacePropertyLocalEnvironment,
8066 : SurfLocalEnv.Name,
8067 : DataLoopNode::NodeFluidType::Air,
8068 : DataLoopNode::ConnectionType::Inlet,
8069 : NodeInputManager::CompFluidStream::Primary,
8070 4 : ObjectIsParent);
8071 2 : if (NodeNum == 0 && CheckOutAirNodeNumber(state, NodeNum)) {
8072 0 : ShowSevereError(state,
8073 0 : format("{} {} = \"{}\", object. Illegal value for \"{}\" has been found.",
8074 : RoutineName,
8075 : cCurrentModuleObject,
8076 : SurfLocalEnv.Name,
8077 0 : state.dataIPShortCut->cAlphaFieldNames(5)));
8078 0 : ShowContinueError(state,
8079 0 : format("{} entered value = \"{}\", no corresponding outdoor air node has been found in the input file.",
8080 0 : state.dataIPShortCut->cAlphaFieldNames(5),
8081 0 : state.dataIPShortCut->cAlphaArgs(5)));
8082 0 : ErrorsFound = true;
8083 : } else {
8084 2 : SurfLocalEnv.OutdoorAirNodePtr = NodeNum;
8085 : }
8086 : }
8087 :
8088 : // get ground surfaces object number;
8089 122 : if (!state.dataIPShortCut->lAlphaFieldBlanks(6)) {
8090 13 : int GndSurfsNum = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(6), state.dataSurface->GroundSurfsProperty);
8091 13 : if (GndSurfsNum == 0) {
8092 0 : ShowSevereError(state,
8093 0 : format("{} {} = \"{}\", object. Illegal value for \"{}\" has been found.",
8094 : RoutineName,
8095 : cCurrentModuleObject,
8096 : SurfLocalEnv.Name,
8097 0 : state.dataIPShortCut->cAlphaFieldNames(6)));
8098 0 : ShowContinueError(
8099 : state,
8100 0 : format("{} entered value = \"{}\", no corresponding ground surfaces object has been found in the input file.",
8101 0 : state.dataIPShortCut->cAlphaFieldNames(6),
8102 0 : state.dataIPShortCut->cAlphaArgs(6)));
8103 0 : ErrorsFound = true;
8104 : } else {
8105 13 : SurfLocalEnv.GroundSurfsPtr = GndSurfsNum;
8106 : }
8107 : }
8108 : }
8109 : }
8110 : // Link surface properties to surface object
8111 44533 : for (int SurfLoop = 1; SurfLoop <= state.dataSurface->TotSurfaces; ++SurfLoop) {
8112 57268 : for (int Loop = 1; Loop <= state.dataSurface->TotSurfLocalEnv; ++Loop) {
8113 13506 : auto &SurfLocalEnv = state.dataSurface->SurfLocalEnvironment(Loop);
8114 13506 : if (SurfLocalEnv.SurfPtr == SurfLoop) {
8115 122 : auto &surface = state.dataSurface->Surface(SurfLoop);
8116 122 : if (SurfLocalEnv.OutdoorAirNodePtr != 0) {
8117 2 : surface.SurfLinkedOutAirNode = SurfLocalEnv.OutdoorAirNodePtr;
8118 : }
8119 122 : if (SurfLocalEnv.ExtShadingSchedPtr != 0) {
8120 102 : surface.SurfSchedExternalShadingFrac = true;
8121 102 : surface.SurfExternalShadingSchInd = SurfLocalEnv.ExtShadingSchedPtr;
8122 : }
8123 122 : if (SurfLocalEnv.SurroundingSurfsPtr != 0) {
8124 6 : surface.SurfHasSurroundingSurfProperty = true;
8125 6 : surface.SurfSurroundingSurfacesNum = SurfLocalEnv.SurroundingSurfsPtr;
8126 : }
8127 122 : if (SurfLocalEnv.GroundSurfsPtr != 0) {
8128 13 : surface.IsSurfPropertyGndSurfacesDefined = true;
8129 13 : surface.UseSurfPropertyGndSurfTemp = true;
8130 13 : surface.UseSurfPropertyGndSurfRefl = true;
8131 13 : surface.SurfPropertyGndSurfIndex = SurfLocalEnv.GroundSurfsPtr;
8132 : }
8133 : }
8134 : }
8135 : }
8136 771 : }
8137 :
8138 771 : void GetSurfaceSrdSurfsData(EnergyPlusData &state, bool &ErrorsFound) // Error flag indicator (true if errors found)
8139 : {
8140 : // SUBROUTINE INFORMATION:
8141 : // AUTHOR X LUO
8142 : // DATE WRITTEN July 2017
8143 : // MODIFIED na
8144 : // RE-ENGINEERED na
8145 :
8146 : // PURPOSE OF THIS SUBROUTINE:
8147 : // load input data for surrounding surfaces properties for exterior surfaces
8148 :
8149 : // Using/Aliasing
8150 : using namespace DataErrorTracking;
8151 : using DataLoopNode::ObjectIsParent;
8152 : using NodeInputManager::GetOnlySingleNode;
8153 : using OutAirNodeManager::CheckOutAirNodeNumber;
8154 : using ScheduleManager::GetScheduleIndex;
8155 :
8156 : // INTERFACE BLOCK SPECIFICATIONS:na
8157 : // DERIVED TYPE DEFINITIONS:na
8158 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
8159 : int NumAlpha;
8160 : int NumNumeric;
8161 : int IOStat;
8162 : int TotSrdSurfProperties;
8163 :
8164 : //-----------------------------------------------------------------------
8165 : // SurfaceProperty:SurroundingSurfaces
8166 : //-----------------------------------------------------------------------
8167 771 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
8168 771 : cCurrentModuleObject = "SurfaceProperty:SurroundingSurfaces";
8169 771 : TotSrdSurfProperties = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
8170 :
8171 771 : if (TotSrdSurfProperties > 0) {
8172 :
8173 2 : if (!allocated(state.dataSurface->SurroundingSurfsProperty)) {
8174 2 : state.dataSurface->SurroundingSurfsProperty.allocate(TotSrdSurfProperties);
8175 : }
8176 :
8177 8 : for (int Loop = 1; Loop <= TotSrdSurfProperties; ++Loop) {
8178 :
8179 6 : auto &SrdSurfsProp = state.dataSurface->SurroundingSurfsProperty(Loop);
8180 :
8181 42 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
8182 : cCurrentModuleObject,
8183 : Loop,
8184 6 : state.dataIPShortCut->cAlphaArgs,
8185 : NumAlpha,
8186 6 : state.dataIPShortCut->rNumericArgs,
8187 : NumNumeric,
8188 : IOStat,
8189 6 : state.dataIPShortCut->lNumericFieldBlanks,
8190 6 : state.dataIPShortCut->lAlphaFieldBlanks,
8191 6 : state.dataIPShortCut->cAlphaFieldNames,
8192 6 : state.dataIPShortCut->cNumericFieldNames);
8193 6 : UtilityRoutines::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
8194 :
8195 : // A1: Name
8196 6 : SrdSurfsProp.Name = state.dataIPShortCut->cAlphaArgs(1);
8197 :
8198 : // N1: sky view factor
8199 6 : if (!state.dataIPShortCut->lNumericFieldBlanks(1)) {
8200 6 : SrdSurfsProp.SkyViewFactor = state.dataIPShortCut->rNumericArgs(1);
8201 6 : SrdSurfsProp.IsSkyViewFactorSet = true;
8202 : }
8203 :
8204 : // A2: sky temp sch name
8205 6 : if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) {
8206 0 : SrdSurfsProp.SkyTempSchNum = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(2));
8207 : }
8208 :
8209 : // N2: ground view factor
8210 6 : if (!state.dataIPShortCut->lNumericFieldBlanks(2)) {
8211 3 : SrdSurfsProp.GroundViewFactor = state.dataIPShortCut->rNumericArgs(2);
8212 3 : SrdSurfsProp.IsGroundViewFactorSet = true;
8213 : }
8214 :
8215 : // A3: ground temp sch name
8216 6 : if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) {
8217 0 : SrdSurfsProp.GroundTempSchNum = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(3));
8218 : }
8219 :
8220 : // The object requires at least one srd surface input, each surface requires a set of 3 fields (2 Alpha fields Name and Temp
8221 : // Sch Name and 1 Num fields View Factor)
8222 6 : if (NumAlpha < 5) {
8223 0 : ShowSevereError(state, format("{} = \"{}\" is not defined correctly.", cCurrentModuleObject, SrdSurfsProp.Name));
8224 0 : ShowContinueError(state, "At lease one set of surrounding surface properties should be defined.");
8225 0 : ErrorsFound = true;
8226 0 : continue;
8227 : }
8228 6 : if ((NumAlpha - 3) / 2 != (NumNumeric - 2)) {
8229 0 : ShowSevereError(state, format("{} = \"{}\" is not defined correctly.", cCurrentModuleObject, SrdSurfsProp.Name));
8230 0 : ShowContinueError(state, "Check number of input fields for each surrounding surface.");
8231 0 : ErrorsFound = true;
8232 0 : continue;
8233 : }
8234 : // Read surrounding surfaces properties
8235 6 : SrdSurfsProp.TotSurroundingSurface = NumNumeric - 1;
8236 6 : SrdSurfsProp.SurroundingSurfs.allocate(SrdSurfsProp.TotSurroundingSurface);
8237 20 : for (int SurfLoop = 1; SurfLoop <= SrdSurfsProp.TotSurroundingSurface; ++SurfLoop) {
8238 14 : SrdSurfsProp.SurroundingSurfs(SurfLoop).Name = state.dataIPShortCut->cAlphaArgs(SurfLoop * 2 + 2);
8239 14 : SrdSurfsProp.SurroundingSurfs(SurfLoop).ViewFactor = state.dataIPShortCut->rNumericArgs(SurfLoop + 2);
8240 14 : SrdSurfsProp.SurroundingSurfs(SurfLoop).TempSchNum = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(SurfLoop * 2 + 3));
8241 : }
8242 : }
8243 : }
8244 771 : }
8245 :
8246 771 : void GetSurfaceGroundSurfsData(EnergyPlusData &state, bool &ErrorsFound)
8247 : {
8248 :
8249 772 : std::string cCurrentModuleObject = "SurfaceProperty:GroundSurfaces";
8250 771 : state.dataSurface->TotSurfPropGndSurfs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
8251 772 : auto const instances = state.dataInputProcessing->inputProcessor->epJSON.find(cCurrentModuleObject);
8252 771 : if (instances == state.dataInputProcessing->inputProcessor->epJSON.end()) {
8253 770 : if (state.dataSurface->TotSurfPropGndSurfs > 0) ErrorsFound = true;
8254 770 : return;
8255 : } else {
8256 1 : auto &instancesValue = instances.value();
8257 6 : for (auto instance = instancesValue.begin(); instance != instancesValue.end(); ++instance) {
8258 5 : auto const &fields = instance.value();
8259 5 : auto const &thisObjectName = instance.key();
8260 10 : GroundSurfacesProperty thisGndSurfsObj;
8261 5 : thisGndSurfsObj.Name = UtilityRoutines::MakeUPPERCase(thisObjectName);
8262 5 : state.dataInputProcessing->inputProcessor->markObjectAsUsed(cCurrentModuleObject, thisObjectName);
8263 10 : auto groundSurfaces = fields.find("ground_surfaces");
8264 5 : if (groundSurfaces != fields.end()) {
8265 10 : auto groundSurfacesArray = groundSurfaces.value();
8266 5 : thisGndSurfsObj.NumGndSurfs = groundSurfacesArray.size();
8267 16 : for (auto groundSurface : groundSurfacesArray) {
8268 22 : GroundSurfacesData thisGndSurf;
8269 22 : auto GndSurfName = groundSurface.find("ground_surface_name");
8270 11 : if (GndSurfName != groundSurface.end()) {
8271 22 : auto ground_surf_name = groundSurface.at("ground_surface_name").get<std::string>();
8272 11 : if (!ground_surf_name.empty()) {
8273 11 : thisGndSurf.Name = EnergyPlus::UtilityRoutines::MakeUPPERCase(ground_surf_name);
8274 : }
8275 : }
8276 22 : auto groundSurfViewFactor = groundSurface.find("ground_surface_view_factor");
8277 11 : if (groundSurfViewFactor != groundSurface.end()) {
8278 11 : thisGndSurf.ViewFactor = groundSurface.at("ground_surface_view_factor").get<Real64>();
8279 11 : thisGndSurfsObj.IsGroundViewFactorSet = true;
8280 : }
8281 22 : auto TempSchName = groundSurface.find("ground_surface_temperature_schedule_name");
8282 11 : if (TempSchName != groundSurface.end()) {
8283 20 : auto gnd_surf_TempSchName = groundSurface.at("ground_surface_temperature_schedule_name").get<std::string>();
8284 10 : if (!gnd_surf_TempSchName.empty()) {
8285 10 : thisGndSurf.TempSchPtr =
8286 20 : ScheduleManager::GetScheduleIndex(state, EnergyPlus::UtilityRoutines::MakeUPPERCase(gnd_surf_TempSchName));
8287 : }
8288 : }
8289 22 : auto ReflSchName = groundSurface.find("ground_surface_reflectance_schedule_name");
8290 11 : if (ReflSchName != groundSurface.end()) {
8291 20 : auto gnd_surf_ReflSchName = groundSurface.at("ground_surface_reflectance_schedule_name").get<std::string>();
8292 10 : if (!gnd_surf_ReflSchName.empty()) {
8293 10 : thisGndSurf.ReflSchPtr =
8294 20 : ScheduleManager::GetScheduleIndex(state, EnergyPlus::UtilityRoutines::MakeUPPERCase(gnd_surf_ReflSchName));
8295 : }
8296 : }
8297 11 : thisGndSurfsObj.GndSurfs.push_back(thisGndSurf);
8298 : }
8299 : }
8300 16 : for (int gSurfNum = 1; gSurfNum <= thisGndSurfsObj.NumGndSurfs; gSurfNum++) {
8301 11 : thisGndSurfsObj.SurfsViewFactorSum += thisGndSurfsObj.GndSurfs(gSurfNum).ViewFactor;
8302 : }
8303 5 : state.dataSurface->GroundSurfsProperty.push_back(thisGndSurfsObj);
8304 : }
8305 : }
8306 : // set report variables
8307 1 : if (state.dataSurface->TotSurfPropGndSurfs > 0) {
8308 6 : for (int Loop = 1; Loop <= state.dataSurface->TotSurfPropGndSurfs; Loop++) {
8309 5 : bool SetTempSchReportVar = true;
8310 5 : bool SetReflSchReportVar = true;
8311 5 : auto &thisGndSurfsObj = state.dataSurface->GroundSurfsProperty(Loop);
8312 16 : for (int gSurfNum = 1; gSurfNum <= thisGndSurfsObj.NumGndSurfs; gSurfNum++) {
8313 11 : if (thisGndSurfsObj.GndSurfs(gSurfNum).TempSchPtr != 0 && SetTempSchReportVar) {
8314 8 : SetupOutputVariable(state,
8315 : "Surfaces Property Ground Surfaces Average Temperature",
8316 : OutputProcessor::Unit::C,
8317 : thisGndSurfsObj.SurfsTempAvg,
8318 : OutputProcessor::SOVTimeStepType::Zone,
8319 : OutputProcessor::SOVStoreType::State,
8320 4 : thisGndSurfsObj.Name);
8321 4 : SetTempSchReportVar = false;
8322 : }
8323 11 : if (thisGndSurfsObj.GndSurfs(gSurfNum).ReflSchPtr != 0 && SetReflSchReportVar) {
8324 8 : SetupOutputVariable(state,
8325 : "Surfaces Property Ground Surfaces Average Reflectance",
8326 : OutputProcessor::Unit::None,
8327 : thisGndSurfsObj.SurfsReflAvg,
8328 : OutputProcessor::SOVTimeStepType::Zone,
8329 : OutputProcessor::SOVStoreType::State,
8330 4 : thisGndSurfsObj.Name);
8331 4 : SetReflSchReportVar = false;
8332 : }
8333 : }
8334 : }
8335 : }
8336 : }
8337 :
8338 771 : void GetSurfaceHeatTransferAlgorithmOverrides(EnergyPlusData &state, bool &ErrorsFound)
8339 : {
8340 :
8341 : // SUBROUTINE INFORMATION:
8342 : // AUTHOR B. Griffith, portions from ApplyConvectionValue by Linda Lawrie
8343 : // DATE WRITTEN July 2012
8344 : // MODIFIED na
8345 : // RE-ENGINEERED na
8346 :
8347 : // PURPOSE OF THIS SUBROUTINE:
8348 : // <description>
8349 :
8350 : // Using/Aliasing
8351 :
8352 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
8353 : int CountHTAlgoObjectsSingleSurf;
8354 : int CountHTAlgoObjectsMultiSurf;
8355 : int CountHTAlgoObjectsSurfList;
8356 : int IOStatus; // Used in GetObjectItem
8357 771 : bool ErrorsFoundSingleSurf(false);
8358 771 : bool ErrorsFoundMultiSurf(false);
8359 771 : bool ErrorsFoundSurfList(false);
8360 771 : bool ErrorsFoundByConstruct(false);
8361 : DataSurfaces::HeatTransferModel tmpAlgoInput;
8362 : int Item;
8363 : int Item1;
8364 : int NumAlphas;
8365 : int NumNumbers;
8366 : int Found;
8367 : bool SurfacesOfType;
8368 : int SurfNum;
8369 : // INTEGER :: Index
8370 : int NumEMPDMat;
8371 : int NumPCMat;
8372 : int NumVTCMat;
8373 : int NumHAMTMat1;
8374 : int NumHAMTMat2;
8375 : int NumHAMTMat3;
8376 : int NumHAMTMat4;
8377 : int NumHAMTMat5;
8378 : int NumHAMTMat6;
8379 : int SumHAMTMat;
8380 : bool msgneeded;
8381 :
8382 771 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
8383 771 : cCurrentModuleObject = "SurfaceProperty:HeatBalanceSourceTerm";
8384 771 : int CountAddHeatSourceSurf = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
8385 :
8386 775 : for (Item = 1; Item <= CountAddHeatSourceSurf; ++Item) {
8387 28 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
8388 : cCurrentModuleObject,
8389 : Item,
8390 4 : state.dataIPShortCut->cAlphaArgs,
8391 : NumAlphas,
8392 4 : state.dataIPShortCut->rNumericArgs,
8393 : NumNumbers,
8394 : IOStatus,
8395 4 : state.dataIPShortCut->lNumericFieldBlanks,
8396 4 : state.dataIPShortCut->lAlphaFieldBlanks,
8397 4 : state.dataIPShortCut->cAlphaFieldNames,
8398 4 : state.dataIPShortCut->cNumericFieldNames);
8399 4 : Found = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(1), state.dataSurface->Surface, state.dataSurface->TotSurfaces);
8400 :
8401 4 : if (Found == 0) {
8402 0 : ShowSevereError(state, cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", did not find matching surface.");
8403 0 : ErrorsFound = true;
8404 8 : } else if (state.dataSurface->Surface(Found).InsideHeatSourceTermSchedule ||
8405 4 : state.dataSurface->Surface(Found).OutsideHeatSourceTermSchedule) {
8406 0 : ShowSevereError(state,
8407 0 : cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
8408 : "\", multiple SurfaceProperty:HeatBalanceSourceTerm objects applied to the same surface.");
8409 0 : ErrorsFound = true;
8410 : }
8411 :
8412 4 : if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) {
8413 1 : state.dataSurface->Surface(Found).InsideHeatSourceTermSchedule =
8414 1 : EnergyPlus::ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(2));
8415 1 : state.dataSurface->AnyHeatBalanceInsideSourceTerm = true;
8416 1 : if (state.dataSurface->Surface(Found).InsideHeatSourceTermSchedule == 0) {
8417 0 : ShowSevereError(state,
8418 0 : cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", cannot find the matching Schedule: " +
8419 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2));
8420 0 : ErrorsFound = true;
8421 : }
8422 : }
8423 :
8424 4 : if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) {
8425 3 : state.dataSurface->Surface(Found).OutsideHeatSourceTermSchedule =
8426 3 : EnergyPlus::ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(3));
8427 3 : state.dataSurface->AnyHeatBalanceOutsideSourceTerm = true;
8428 3 : if (state.dataSurface->Surface(Found).OutsideHeatSourceTermSchedule == 0) {
8429 0 : ShowSevereError(state,
8430 0 : cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", cannot find the matching Schedule: " +
8431 0 : state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3));
8432 0 : ErrorsFound = true;
8433 3 : } else if (state.dataSurface->Surface(Found).OSCPtr > 0) {
8434 0 : ShowSevereError(state,
8435 0 : cCurrentModuleObject +
8436 0 : "=\"SurfaceProperty:HeatBalanceSourceTerm\", cannot be specified for OtherSideCoefficient Surface=" +
8437 0 : state.dataIPShortCut->cAlphaArgs(1));
8438 0 : ErrorsFound = true;
8439 : }
8440 : }
8441 :
8442 5 : if (state.dataSurface->Surface(Found).OutsideHeatSourceTermSchedule == 0 &&
8443 1 : state.dataSurface->Surface(Found).InsideHeatSourceTermSchedule == 0) {
8444 0 : ShowSevereError(state,
8445 0 : cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
8446 : "\", no schedule defined for additional heat source.");
8447 0 : ErrorsFound = true;
8448 : }
8449 : }
8450 :
8451 : // first initialize each heat transfer surface with the overall model type, array assignment
8452 44533 : for (auto &e : state.dataSurface->Surface)
8453 43762 : e.HeatTransferAlgorithm = state.dataHeatBal->OverallHeatTransferSolutionAlgo;
8454 :
8455 771 : cCurrentModuleObject = "SurfaceProperty:HeatTransferAlgorithm";
8456 771 : CountHTAlgoObjectsSingleSurf = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
8457 :
8458 771 : cCurrentModuleObject = "SurfaceProperty:HeatTransferAlgorithm";
8459 773 : for (Item = 1; Item <= CountHTAlgoObjectsSingleSurf; ++Item) {
8460 14 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
8461 : cCurrentModuleObject,
8462 : Item,
8463 2 : state.dataIPShortCut->cAlphaArgs,
8464 : NumAlphas,
8465 2 : state.dataIPShortCut->rNumericArgs,
8466 : NumNumbers,
8467 : IOStatus,
8468 2 : state.dataIPShortCut->lNumericFieldBlanks,
8469 2 : state.dataIPShortCut->lAlphaFieldBlanks,
8470 2 : state.dataIPShortCut->cAlphaFieldNames,
8471 2 : state.dataIPShortCut->cNumericFieldNames);
8472 2 : ErrorsFoundSingleSurf = false;
8473 2 : Found = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(1), state.dataSurface->Surface, state.dataSurface->TotSurfaces);
8474 :
8475 2 : if (Found == 0) {
8476 0 : ShowSevereError(state, cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", did not find matching surface.");
8477 0 : ErrorsFoundSingleSurf = true;
8478 : }
8479 :
8480 : {
8481 4 : auto const SELECT_CASE_var(state.dataIPShortCut->cAlphaArgs(2));
8482 :
8483 2 : if (SELECT_CASE_var == "CONDUCTIONTRANSFERFUNCTION") {
8484 0 : tmpAlgoInput = DataSurfaces::HeatTransferModel::CTF;
8485 0 : state.dataHeatBal->AnyCTF = true;
8486 2 : } else if (SELECT_CASE_var == "MOISTUREPENETRATIONDEPTHCONDUCTIONTRANSFERFUNCTION") {
8487 1 : tmpAlgoInput = DataSurfaces::HeatTransferModel::EMPD;
8488 1 : state.dataHeatBal->AnyEMPD = true;
8489 1 : } else if (SELECT_CASE_var == "COMBINEDHEATANDMOISTUREFINITEELEMENT") {
8490 0 : tmpAlgoInput = DataSurfaces::HeatTransferModel::HAMT;
8491 0 : state.dataHeatBal->AnyHAMT = true;
8492 1 : } else if (SELECT_CASE_var == "CONDUCTIONFINITEDIFFERENCE") {
8493 1 : tmpAlgoInput = DataSurfaces::HeatTransferModel::CondFD;
8494 1 : state.dataHeatBal->AnyCondFD = true;
8495 : } else {
8496 0 : ShowSevereError(state,
8497 0 : cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", invalid " +
8498 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2));
8499 0 : ErrorsFoundSingleSurf = true;
8500 : }
8501 : }
8502 :
8503 2 : if (!ErrorsFoundSingleSurf) {
8504 2 : state.dataSurface->Surface(Found).HeatTransferAlgorithm = tmpAlgoInput;
8505 : } else {
8506 0 : ErrorsFound = true;
8507 : }
8508 : } // single surface heat transfer algorithm override
8509 :
8510 771 : cCurrentModuleObject = "SurfaceProperty:HeatTransferAlgorithm:MultipleSurface";
8511 771 : CountHTAlgoObjectsMultiSurf = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
8512 :
8513 771 : for (Item = 1; Item <= CountHTAlgoObjectsMultiSurf; ++Item) {
8514 0 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
8515 : cCurrentModuleObject,
8516 : Item,
8517 0 : state.dataIPShortCut->cAlphaArgs,
8518 : NumAlphas,
8519 0 : state.dataIPShortCut->rNumericArgs,
8520 : NumNumbers,
8521 : IOStatus,
8522 0 : state.dataIPShortCut->lNumericFieldBlanks,
8523 0 : state.dataIPShortCut->lAlphaFieldBlanks,
8524 0 : state.dataIPShortCut->cAlphaFieldNames,
8525 0 : state.dataIPShortCut->cNumericFieldNames);
8526 0 : ErrorsFoundMultiSurf = false;
8527 : {
8528 0 : auto const SELECT_CASE_var(state.dataIPShortCut->cAlphaArgs(3));
8529 :
8530 0 : if (SELECT_CASE_var == "CONDUCTIONTRANSFERFUNCTION") {
8531 0 : tmpAlgoInput = DataSurfaces::HeatTransferModel::CTF;
8532 0 : state.dataHeatBal->AnyCTF = true;
8533 0 : } else if (SELECT_CASE_var == "MOISTUREPENETRATIONDEPTHCONDUCTIONTRANSFERFUNCTION") {
8534 0 : tmpAlgoInput = DataSurfaces::HeatTransferModel::EMPD;
8535 0 : state.dataHeatBal->AnyEMPD = true;
8536 0 : } else if (SELECT_CASE_var == "COMBINEDHEATANDMOISTUREFINITEELEMENT") {
8537 0 : tmpAlgoInput = DataSurfaces::HeatTransferModel::HAMT;
8538 0 : state.dataHeatBal->AnyHAMT = true;
8539 0 : } else if (SELECT_CASE_var == "CONDUCTIONFINITEDIFFERENCE") {
8540 0 : tmpAlgoInput = DataSurfaces::HeatTransferModel::CondFD;
8541 0 : state.dataHeatBal->AnyCondFD = true;
8542 : } else {
8543 0 : ShowSevereError(state,
8544 0 : cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", invalid " +
8545 0 : state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3));
8546 0 : ErrorsFoundMultiSurf = true;
8547 : }
8548 : }
8549 :
8550 : {
8551 0 : auto const SELECT_CASE_var(state.dataIPShortCut->cAlphaArgs(2));
8552 :
8553 0 : if (SELECT_CASE_var == "ALLEXTERIORSURFACES") {
8554 0 : SurfacesOfType = false;
8555 0 : for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
8556 0 : if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) continue;
8557 0 : if (state.dataSurface->Surface(SurfNum).ExtBoundCond > 0) continue; // Interior surfaces
8558 0 : if (state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).TypeIsWindow) continue;
8559 0 : SurfacesOfType = true;
8560 0 : state.dataSurface->Surface(SurfNum).HeatTransferAlgorithm = tmpAlgoInput;
8561 : }
8562 :
8563 0 : } else if (SELECT_CASE_var == "ALLEXTERIORWALLS") {
8564 0 : SurfacesOfType = false;
8565 0 : for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
8566 0 : if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) continue;
8567 0 : if (state.dataSurface->Surface(SurfNum).ExtBoundCond > 0) continue; // Interior surfaces
8568 :
8569 0 : if (state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Wall) continue;
8570 0 : if (state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).TypeIsWindow) continue;
8571 0 : SurfacesOfType = true;
8572 0 : state.dataSurface->Surface(SurfNum).HeatTransferAlgorithm = tmpAlgoInput;
8573 : }
8574 :
8575 0 : } else if (SELECT_CASE_var == "ALLEXTERIORROOFS") {
8576 0 : SurfacesOfType = false;
8577 0 : for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
8578 0 : if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) continue;
8579 0 : if (state.dataSurface->Surface(SurfNum).ExtBoundCond > 0) continue; // Interior surfaces
8580 0 : if (state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Roof) continue;
8581 0 : if (state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).TypeIsWindow) continue;
8582 0 : SurfacesOfType = true;
8583 0 : state.dataSurface->Surface(SurfNum).HeatTransferAlgorithm = tmpAlgoInput;
8584 : }
8585 :
8586 0 : } else if (SELECT_CASE_var == "ALLEXTERIORFLOORS") {
8587 0 : SurfacesOfType = false;
8588 0 : for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
8589 0 : if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) continue;
8590 0 : if (state.dataSurface->Surface(SurfNum).ExtBoundCond > 0) continue; // Interior surfaces
8591 0 : if (state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Floor) continue;
8592 0 : if (state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).TypeIsWindow) continue;
8593 0 : SurfacesOfType = true;
8594 0 : state.dataSurface->Surface(SurfNum).HeatTransferAlgorithm = tmpAlgoInput;
8595 : }
8596 :
8597 0 : } else if (SELECT_CASE_var == "ALLGROUNDCONTACTSURFACES") {
8598 0 : SurfacesOfType = false;
8599 0 : for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
8600 0 : if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) continue;
8601 0 : if (state.dataSurface->Surface(SurfNum).ExtBoundCond != Ground) continue; // ground BC
8602 0 : if (state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).TypeIsWindow) continue;
8603 0 : SurfacesOfType = true;
8604 0 : state.dataSurface->Surface(SurfNum).HeatTransferAlgorithm = tmpAlgoInput;
8605 : }
8606 0 : } else if (SELECT_CASE_var == "ALLINTERIORSURFACES") {
8607 0 : SurfacesOfType = false;
8608 0 : for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
8609 0 : if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) continue;
8610 0 : if (state.dataSurface->Surface(SurfNum).ExtBoundCond <= 0) continue; // Exterior surfaces
8611 0 : if (state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).TypeIsWindow) continue;
8612 0 : SurfacesOfType = true;
8613 0 : state.dataSurface->Surface(SurfNum).HeatTransferAlgorithm = tmpAlgoInput;
8614 : }
8615 :
8616 0 : } else if (SELECT_CASE_var == "ALLINTERIORWALLS") {
8617 0 : SurfacesOfType = false;
8618 0 : for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
8619 0 : if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) continue;
8620 0 : if (state.dataSurface->Surface(SurfNum).ExtBoundCond <= 0) continue; // Exterior surfaces
8621 0 : if (state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Wall) continue;
8622 0 : if (state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).TypeIsWindow) continue;
8623 0 : SurfacesOfType = true;
8624 0 : state.dataSurface->Surface(SurfNum).HeatTransferAlgorithm = tmpAlgoInput;
8625 : }
8626 :
8627 0 : } else if ((SELECT_CASE_var == "ALLINTERIORROOFS") || (SELECT_CASE_var == "ALLINTERIORCEILINGS")) {
8628 0 : SurfacesOfType = false;
8629 0 : for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
8630 0 : if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) continue;
8631 0 : if (state.dataSurface->Surface(SurfNum).ExtBoundCond <= 0) continue; // Exterior surfaces
8632 0 : if (state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Roof) continue;
8633 0 : if (state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).TypeIsWindow) continue;
8634 0 : SurfacesOfType = true;
8635 0 : state.dataSurface->Surface(SurfNum).HeatTransferAlgorithm = tmpAlgoInput;
8636 : }
8637 :
8638 0 : } else if (SELECT_CASE_var == "ALLINTERIORFLOORS") {
8639 0 : SurfacesOfType = false;
8640 0 : for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
8641 0 : if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) continue;
8642 0 : if (state.dataSurface->Surface(SurfNum).ExtBoundCond <= 0) continue; // Exterior surfaces
8643 0 : if (state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Floor) continue;
8644 0 : if (state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).TypeIsWindow) continue;
8645 0 : SurfacesOfType = true;
8646 0 : state.dataSurface->Surface(SurfNum).HeatTransferAlgorithm = tmpAlgoInput;
8647 : }
8648 : } else {
8649 0 : SurfacesOfType = false;
8650 0 : ShowSevereError(state,
8651 0 : cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", invalid " +
8652 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2));
8653 0 : ErrorsFoundMultiSurf = true;
8654 : }
8655 : }
8656 :
8657 0 : if (!SurfacesOfType) {
8658 0 : ShowWarningError(state,
8659 0 : "In " + cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
8660 0 : "\", for Multiple Surface Assignment=\"" + state.dataIPShortCut->cAlphaArgs(2) +
8661 : "\", there were no surfaces of that type found for assignment.");
8662 : }
8663 0 : if (ErrorsFoundMultiSurf) ErrorsFound = true;
8664 :
8665 : } // multi surface heat transfer algo override
8666 :
8667 771 : cCurrentModuleObject = "SurfaceProperty:HeatTransferAlgorithm:SurfaceList";
8668 771 : CountHTAlgoObjectsSurfList = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
8669 772 : for (Item = 1; Item <= CountHTAlgoObjectsSurfList; ++Item) {
8670 7 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
8671 : cCurrentModuleObject,
8672 : Item,
8673 1 : state.dataIPShortCut->cAlphaArgs,
8674 : NumAlphas,
8675 1 : state.dataIPShortCut->rNumericArgs,
8676 : NumNumbers,
8677 : IOStatus,
8678 1 : state.dataIPShortCut->lNumericFieldBlanks,
8679 1 : state.dataIPShortCut->lAlphaFieldBlanks,
8680 1 : state.dataIPShortCut->cAlphaFieldNames,
8681 1 : state.dataIPShortCut->cNumericFieldNames);
8682 1 : ErrorsFoundSurfList = false;
8683 : {
8684 2 : auto const SELECT_CASE_var(state.dataIPShortCut->cAlphaArgs(2));
8685 :
8686 1 : if (SELECT_CASE_var == "CONDUCTIONTRANSFERFUNCTION") {
8687 0 : tmpAlgoInput = DataSurfaces::HeatTransferModel::CTF;
8688 0 : state.dataHeatBal->AnyCTF = true;
8689 1 : } else if (SELECT_CASE_var == "MOISTUREPENETRATIONDEPTHCONDUCTIONTRANSFERFUNCTION") {
8690 1 : tmpAlgoInput = DataSurfaces::HeatTransferModel::EMPD;
8691 1 : state.dataHeatBal->AnyEMPD = true;
8692 0 : } else if (SELECT_CASE_var == "COMBINEDHEATANDMOISTUREFINITEELEMENT") {
8693 0 : tmpAlgoInput = DataSurfaces::HeatTransferModel::HAMT;
8694 0 : state.dataHeatBal->AnyHAMT = true;
8695 0 : } else if (SELECT_CASE_var == "CONDUCTIONFINITEDIFFERENCE") {
8696 0 : tmpAlgoInput = DataSurfaces::HeatTransferModel::CondFD;
8697 0 : state.dataHeatBal->AnyCondFD = true;
8698 : } else {
8699 0 : ShowSevereError(state,
8700 0 : cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", invalid " +
8701 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2));
8702 0 : ErrorsFoundSurfList = true;
8703 : }
8704 : }
8705 :
8706 3 : for (Item1 = 3; Item1 <= NumAlphas; ++Item1) {
8707 :
8708 6 : Found = UtilityRoutines::FindItemInList(
8709 6 : state.dataIPShortCut->cAlphaArgs(Item1), state.dataSurface->Surface, state.dataSurface->TotSurfaces);
8710 :
8711 2 : if (Found == 0) {
8712 0 : ShowSevereError(state, cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", did not find matching surface.");
8713 0 : ShowContinueError(state, "Name of surface not found = \"" + state.dataIPShortCut->cAlphaArgs(Item1) + "\"");
8714 0 : ErrorsFoundSurfList = true;
8715 : }
8716 :
8717 2 : if (!ErrorsFoundSurfList) {
8718 2 : state.dataSurface->Surface(Found).HeatTransferAlgorithm = tmpAlgoInput;
8719 : } else {
8720 0 : ErrorsFound = true;
8721 : }
8722 : }
8723 : }
8724 :
8725 771 : cCurrentModuleObject = "SurfaceProperty:HeatTransferAlgorithm:Construction";
8726 771 : CountHTAlgoObjectsSurfList = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
8727 772 : for (Item = 1; Item <= CountHTAlgoObjectsSurfList; ++Item) {
8728 7 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
8729 : cCurrentModuleObject,
8730 : Item,
8731 1 : state.dataIPShortCut->cAlphaArgs,
8732 : NumAlphas,
8733 1 : state.dataIPShortCut->rNumericArgs,
8734 : NumNumbers,
8735 : IOStatus,
8736 1 : state.dataIPShortCut->lNumericFieldBlanks,
8737 1 : state.dataIPShortCut->lAlphaFieldBlanks,
8738 1 : state.dataIPShortCut->cAlphaFieldNames,
8739 1 : state.dataIPShortCut->cNumericFieldNames);
8740 1 : ErrorsFoundByConstruct = false;
8741 : {
8742 2 : auto const SELECT_CASE_var(state.dataIPShortCut->cAlphaArgs(2));
8743 :
8744 1 : if (SELECT_CASE_var == "CONDUCTIONTRANSFERFUNCTION") {
8745 0 : tmpAlgoInput = DataSurfaces::HeatTransferModel::CTF;
8746 0 : state.dataHeatBal->AnyCTF = true;
8747 1 : } else if (SELECT_CASE_var == "MOISTUREPENETRATIONDEPTHCONDUCTIONTRANSFERFUNCTION") {
8748 0 : tmpAlgoInput = DataSurfaces::HeatTransferModel::EMPD;
8749 0 : state.dataHeatBal->AnyEMPD = true;
8750 1 : } else if (SELECT_CASE_var == "COMBINEDHEATANDMOISTUREFINITEELEMENT") {
8751 1 : tmpAlgoInput = DataSurfaces::HeatTransferModel::HAMT;
8752 1 : state.dataHeatBal->AnyHAMT = true;
8753 0 : } else if (SELECT_CASE_var == "CONDUCTIONFINITEDIFFERENCE") {
8754 0 : tmpAlgoInput = DataSurfaces::HeatTransferModel::CondFD;
8755 0 : state.dataHeatBal->AnyCondFD = true;
8756 : } else {
8757 0 : ShowSevereError(state,
8758 0 : cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", invalid " +
8759 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2));
8760 0 : ErrorsFoundByConstruct = true;
8761 : }
8762 : }
8763 :
8764 3 : Found = UtilityRoutines::FindItemInList(
8765 3 : state.dataIPShortCut->cAlphaArgs(3), state.dataConstruction->Construct, state.dataHeatBal->TotConstructs);
8766 1 : if (Found == 0) {
8767 0 : ShowSevereError(state,
8768 0 : cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", invalid " +
8769 0 : state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3));
8770 0 : ErrorsFoundByConstruct = true;
8771 : }
8772 :
8773 1 : if (!ErrorsFoundByConstruct) {
8774 7 : for (Item1 = 1; Item1 <= state.dataSurface->TotSurfaces; ++Item1) {
8775 6 : if (state.dataSurface->Surface(Item1).Construction == Found) {
8776 1 : state.dataSurface->Surface(Item1).HeatTransferAlgorithm = tmpAlgoInput;
8777 : }
8778 : }
8779 : }
8780 : }
8781 :
8782 : // Change algorithm for Kiva and air boundary foundation surfaces
8783 44533 : for (auto &surf : state.dataSurface->Surface) {
8784 43762 : if (surf.ExtBoundCond == KivaFoundation) {
8785 38 : surf.HeatTransferAlgorithm = DataSurfaces::HeatTransferModel::Kiva;
8786 38 : state.dataHeatBal->AnyKiva = true;
8787 : }
8788 : }
8789 :
8790 : // test for missing materials for algorithms selected
8791 771 : NumEMPDMat = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "MaterialProperty:MoisturePenetrationDepth:Settings");
8792 2313 : NumPCMat = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "MaterialProperty:PhaseChange") +
8793 1542 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "MaterialProperty:PhaseChangeHysteresis");
8794 771 : NumVTCMat = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "MaterialProperty:VariableThermalConductivity");
8795 771 : NumHAMTMat1 = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "MaterialProperty:HeatAndMoistureTransfer:Settings");
8796 771 : NumHAMTMat2 =
8797 1542 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "MaterialProperty:HeatAndMoistureTransfer:SorptionIsotherm");
8798 771 : NumHAMTMat3 = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "MaterialProperty:HeatAndMoistureTransfer:Suction");
8799 771 : NumHAMTMat4 = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "MaterialProperty:HeatAndMoistureTransfer:Redistribution");
8800 771 : NumHAMTMat5 = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "MaterialProperty:HeatAndMoistureTransfer:Diffusion");
8801 771 : NumHAMTMat6 =
8802 1542 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "MaterialProperty:HeatAndMoistureTransfer:ThermalConductivity");
8803 771 : SumHAMTMat = NumHAMTMat1 + NumHAMTMat2 + NumHAMTMat3 + NumHAMTMat4 + NumHAMTMat5 + NumHAMTMat6;
8804 771 : msgneeded = false;
8805 :
8806 771 : if (NumEMPDMat > 0 && !state.dataHeatBal->AnyEMPD) {
8807 0 : ShowWarningError(state,
8808 0 : format("The input file includes {} MaterialProperty:MoisturePenetrationDepth:Settings objects but the moisture "
8809 : "penetration depth algorithm is not used anywhere.",
8810 0 : NumEMPDMat));
8811 0 : msgneeded = true;
8812 : }
8813 771 : if (NumPCMat > 0 && !state.dataHeatBal->AnyCondFD) {
8814 0 : ShowWarningError(state,
8815 0 : format("The input file includes {} MaterialProperty:PhaseChange objects but the conduction finite difference algorithm "
8816 : "is not used anywhere.",
8817 0 : NumPCMat));
8818 0 : msgneeded = true;
8819 : }
8820 771 : if (NumVTCMat > 0 && !state.dataHeatBal->AnyCondFD) {
8821 0 : ShowWarningError(state,
8822 0 : format("The input file includes {} MaterialProperty:VariableThermalConductivity objects but the conduction finite "
8823 : "difference algorithm is not used anywhere.",
8824 0 : NumVTCMat));
8825 0 : msgneeded = true;
8826 : }
8827 771 : if (SumHAMTMat > 0 && !state.dataHeatBal->AnyHAMT) {
8828 0 : ShowWarningError(state,
8829 0 : format("The input file includes {} MaterialProperty:HeatAndMoistureTransfer:* objects but the combined heat and "
8830 : "moisture finite difference algorithm is not used anywhere.",
8831 0 : SumHAMTMat));
8832 0 : msgneeded = true;
8833 : }
8834 771 : if (msgneeded) {
8835 0 : ShowContinueError(state, "Previous materials will be ignored due to HeatBalanceAlgorithm choice.");
8836 : }
8837 771 : msgneeded = false;
8838 771 : if (NumEMPDMat == 0 && state.dataHeatBal->AnyEMPD) {
8839 0 : ShowWarningError(state,
8840 : "The moisture penetration depth conduction transfer function algorithm is used but the input file includes no "
8841 : "MaterialProperty:MoisturePenetrationDepth:Settings objects.");
8842 0 : msgneeded = true;
8843 : }
8844 771 : if (SumHAMTMat == 0 && state.dataHeatBal->AnyHAMT) {
8845 0 : ShowWarningError(state,
8846 : "The combined heat and moisture finite element algorithm is used but the input file includes no "
8847 : "MaterialProperty:HeatAndMoistureTransfer:* objects.");
8848 0 : msgneeded = true;
8849 : }
8850 771 : if (msgneeded) {
8851 0 : ShowContinueError(state,
8852 : "Certain materials objects are necessary to achieve proper results with the heat transfer algorithm(s) selected.");
8853 : }
8854 :
8855 : // Write Solution Algorithm to the initialization output file for User Verification
8856 771 : print(state.files.eio,
8857 : "{}\n",
8858 : "! <Surface Heat Transfer Algorithm>, Value {CTF - ConductionTransferFunction | EMPD - "
8859 : "MoisturePenetrationDepthConductionTransferFunction | CondFD - ConductionFiniteDifference | HAMT - "
8860 : "CombinedHeatAndMoistureFiniteElement} - Description,Inside Surface Max Temperature Limit{C}, Surface "
8861 771 : "Convection Coefficient Lower Limit {W/m2-K}, Surface Convection Coefficient Upper Limit {W/m2-K}");
8862 :
8863 771 : int numberOfHeatTransferAlgosUsed = 0;
8864 : // Formats
8865 : static constexpr std::string_view Format_725("Surface Heat Transfer Algorithm, {},{:.0R},{:.2R},{:.1R}\n");
8866 :
8867 771 : if (state.dataHeatBal->AnyCTF) {
8868 758 : const auto AlgoName = "CTF - ConductionTransferFunction";
8869 758 : ++numberOfHeatTransferAlgosUsed;
8870 2274 : print(state.files.eio,
8871 : Format_725,
8872 : AlgoName,
8873 758 : state.dataHeatBalSurf->MaxSurfaceTempLimit,
8874 758 : state.dataHeatBal->LowHConvLimit,
8875 758 : state.dataHeatBal->HighHConvLimit);
8876 : }
8877 771 : if (state.dataHeatBal->AnyEMPD) {
8878 2 : state.dataHeatBal->AllCTF = false;
8879 2 : const auto AlgoName = "EMPD - MoisturePenetrationDepthConductionTransferFunction";
8880 2 : ++numberOfHeatTransferAlgosUsed;
8881 6 : print(state.files.eio,
8882 : Format_725,
8883 : AlgoName,
8884 2 : state.dataHeatBalSurf->MaxSurfaceTempLimit,
8885 2 : state.dataHeatBal->LowHConvLimit,
8886 2 : state.dataHeatBal->HighHConvLimit);
8887 2 : if (state.dataHeatBal->doSpaceHeatBalanceSimulation || state.dataHeatBal->doSpaceHeatBalanceSizing) {
8888 0 : ShowSevereError(
8889 : state,
8890 : "MoisturePenetrationDepthConductionTransferFunction is not supported with ZoneAirHeatBalanceAlgorithm Space Heat Balance.");
8891 0 : ErrorsFound = true;
8892 : }
8893 : }
8894 771 : if (state.dataHeatBal->AnyCondFD) {
8895 11 : state.dataHeatBal->AllCTF = false;
8896 11 : const auto AlgoName = "CondFD - ConductionFiniteDifference";
8897 11 : ++numberOfHeatTransferAlgosUsed;
8898 33 : print(state.files.eio,
8899 : Format_725,
8900 : AlgoName,
8901 11 : state.dataHeatBalSurf->MaxSurfaceTempLimit,
8902 11 : state.dataHeatBal->LowHConvLimit,
8903 11 : state.dataHeatBal->HighHConvLimit);
8904 : }
8905 771 : if (state.dataHeatBal->AnyHAMT) {
8906 3 : state.dataHeatBal->AllCTF = false;
8907 3 : const auto AlgoName = "HAMT - CombinedHeatAndMoistureFiniteElement";
8908 3 : ++numberOfHeatTransferAlgosUsed;
8909 9 : print(state.files.eio,
8910 : Format_725,
8911 : AlgoName,
8912 3 : state.dataHeatBalSurf->MaxSurfaceTempLimit,
8913 3 : state.dataHeatBal->LowHConvLimit,
8914 3 : state.dataHeatBal->HighHConvLimit);
8915 3 : if (state.dataHeatBal->doSpaceHeatBalanceSimulation || state.dataHeatBal->doSpaceHeatBalanceSizing) {
8916 0 : ShowSevereError(state, "CombinedHeatAndMoistureFiniteElement is not supported with ZoneAirHeatBalanceAlgorithm Space Heat Balance.");
8917 0 : ErrorsFound = true;
8918 : }
8919 : }
8920 771 : if (state.dataHeatBal->AnyKiva) {
8921 9 : state.dataHeatBal->AllCTF = false;
8922 9 : const auto AlgoName = "KivaFoundation - TwoDimensionalFiniteDifference";
8923 9 : ++numberOfHeatTransferAlgosUsed;
8924 27 : print(state.files.eio,
8925 : Format_725,
8926 : AlgoName,
8927 9 : state.dataHeatBalSurf->MaxSurfaceTempLimit,
8928 9 : state.dataHeatBal->LowHConvLimit,
8929 9 : state.dataHeatBal->HighHConvLimit);
8930 : }
8931 :
8932 : // Check HeatTransferAlgorithm for interior surfaces
8933 771 : if (numberOfHeatTransferAlgosUsed > 1) {
8934 : int ExtSurfNum;
8935 506 : for (Item = 1; Item <= state.dataSurface->TotSurfaces; ++Item) {
8936 496 : auto &surf = state.dataSurface->Surface(Item);
8937 496 : if (surf.ExtBoundCond > 0) {
8938 560 : if ((surf.HeatTransferAlgorithm == DataSurfaces::HeatTransferModel::Invalid) ||
8939 280 : (surf.HeatTransferAlgorithm == DataSurfaces::HeatTransferModel::None))
8940 0 : continue;
8941 280 : ExtSurfNum = surf.ExtBoundCond;
8942 280 : auto &extSurf = state.dataSurface->Surface(ExtSurfNum);
8943 280 : if (surf.HeatTransferAlgorithm != extSurf.HeatTransferAlgorithm) {
8944 0 : ShowWarningError(state,
8945 : "An interior surface is defined as two surfaces with reverse constructions. The HeatTransferAlgorithm in "
8946 : "both constructions should be same.");
8947 0 : ShowContinueError(state,
8948 0 : format("The HeatTransferAlgorithm of Surface: {}, is {}",
8949 : surf.Name,
8950 0 : DataSurfaces::HeatTransAlgoStrs[static_cast<int>(surf.HeatTransferAlgorithm)]));
8951 0 : ShowContinueError(state,
8952 0 : format("The HeatTransferAlgorithm of Surface: {}, is {}",
8953 : extSurf.Name,
8954 0 : DataSurfaces::HeatTransAlgoStrs[static_cast<int>(extSurf.HeatTransferAlgorithm)]));
8955 0 : if (surf.HeatTransferAlgorithm > extSurf.HeatTransferAlgorithm) {
8956 0 : ShowContinueError(state,
8957 0 : format("The HeatTransferAlgorithm of Surface: {}, is assigned to {}. Simulation continues.",
8958 : extSurf.Name,
8959 0 : DataSurfaces::HeatTransAlgoStrs[static_cast<int>(surf.HeatTransferAlgorithm)]));
8960 0 : extSurf.HeatTransferAlgorithm = surf.HeatTransferAlgorithm;
8961 : } else {
8962 0 : ShowContinueError(state,
8963 0 : format("The HeatTransferAlgorithm of Surface: {}, is assigned to {}. Simulation continues.",
8964 : surf.Name,
8965 0 : DataSurfaces::HeatTransAlgoStrs[static_cast<int>(extSurf.HeatTransferAlgorithm)]));
8966 0 : surf.HeatTransferAlgorithm = extSurf.HeatTransferAlgorithm;
8967 : }
8968 : }
8969 : }
8970 : }
8971 : }
8972 :
8973 : // Assign model type to windows, shading surfaces, and TDDs
8974 44533 : for (Item = 1; Item <= state.dataSurface->TotSurfaces; ++Item) {
8975 43762 : if (state.dataSurface->Surface(Item).Class == SurfaceClass::Window || state.dataSurface->Surface(Item).Class == SurfaceClass::GlassDoor) {
8976 : // todo, add complex fenestration switch HeatTransferModel_ComplexFenestration
8977 5974 : if (state.dataSurface->SurfWinWindowModelType(Item) == WindowModel::BSDF) {
8978 0 : state.dataSurface->Surface(Item).HeatTransferAlgorithm = DataSurfaces::HeatTransferModel::ComplexFenestration;
8979 : } else {
8980 5974 : state.dataSurface->Surface(Item).HeatTransferAlgorithm = DataSurfaces::HeatTransferModel::Window5;
8981 : }
8982 : }
8983 131246 : if (state.dataSurface->Surface(Item).Class == SurfaceClass::Detached_B ||
8984 87344 : state.dataSurface->Surface(Item).Class == SurfaceClass::Detached_F ||
8985 171824 : state.dataSurface->Surface(Item).Class == SurfaceClass::Shading || state.dataSurface->Surface(Item).Class == SurfaceClass::Overhang ||
8986 42220 : state.dataSurface->Surface(Item).Class == SurfaceClass::Fin) {
8987 1542 : state.dataSurface->Surface(Item).HeatTransferAlgorithm = DataSurfaces::HeatTransferModel::None;
8988 : }
8989 87524 : if (state.dataSurface->Surface(Item).Class == SurfaceClass::TDD_Diffuser ||
8990 43762 : state.dataSurface->Surface(Item).Class == SurfaceClass::TDD_Dome) {
8991 2 : state.dataSurface->Surface(Item).HeatTransferAlgorithm = DataSurfaces::HeatTransferModel::TDD;
8992 : }
8993 :
8994 51505 : if (state.dataSurface->Surface(Item).HeatTransferAlgorithm == DataSurfaces::HeatTransferModel::CTF ||
8995 7743 : state.dataSurface->Surface(Item).HeatTransferAlgorithm == DataSurfaces::HeatTransferModel::EMPD) {
8996 36062 : state.dataConstruction->Construct(state.dataSurface->Surface(Item).Construction).IsUsedCTF = true;
8997 : }
8998 : }
8999 771 : }
9000 :
9001 40093 : void GetVertices(EnergyPlusData &state,
9002 : int const SurfNum, // Current surface number
9003 : int const NSides, // Number of sides to figure
9004 : Array1S<Real64> const Vertices // Vertices, in specified order
9005 : )
9006 : {
9007 :
9008 : // SUBROUTINE INFORMATION:
9009 : // AUTHOR Linda Lawrie
9010 : // DATE WRITTEN May 2000
9011 : // MODIFIED na
9012 : // RE-ENGINEERED na
9013 :
9014 : // PURPOSE OF THIS SUBROUTINE:
9015 : // This subroutine gets the surface vertices from the arrays
9016 : // passed by the calling routine. These had previously been obtained
9017 : // from the InputProcessor (GetObjectItem). This routine will provide
9018 : // a standard place for determining various properties of the surface
9019 : // from the vertices.
9020 :
9021 : // METHODOLOGY EMPLOYED:
9022 : // na
9023 :
9024 : // REFERENCES:
9025 : // na
9026 :
9027 : // Using/Aliasing
9028 : using namespace Vectors;
9029 :
9030 : using namespace DataErrorTracking;
9031 :
9032 : // SUBROUTINE ARGUMENT DEFINITIONS:
9033 :
9034 : // SUBROUTINE PARAMETER DEFINITIONS:
9035 : static constexpr std::string_view RoutineName("GetVertices: ");
9036 :
9037 : // INTERFACE BLOCK SPECIFICATIONS
9038 : // na
9039 :
9040 : // DERIVED TYPE DEFINITIONS
9041 : // na
9042 :
9043 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
9044 : int Ptr; // Pointer into Vertice array
9045 : int n; // Loop counter
9046 : int NSrc; // Used for CW -> CCW transformation
9047 : int NTar; // Used for CW -> CCW transformation
9048 : Real64 SurfWorldAz;
9049 : Real64 SurfTilt;
9050 : Real64 Perimeter; // Perimeter length of the surface
9051 : Real64 Xb; // Intermediate calculation
9052 : Real64 Yb; // Intermediate calculation
9053 : int ZoneNum;
9054 : int ThisCorner;
9055 80186 : std::string TiltString;
9056 : Real64 ThisWidth;
9057 : Real64 ThisHeight;
9058 : Real64 DistanceCheck;
9059 : // unused REAL(r64) :: ccwtest
9060 : // unused LOGICAL :: SurfaceCCW
9061 : Real64 dotp;
9062 :
9063 : // Object Data
9064 80186 : Vector const TestVector(0.0, 0.0, 1.0);
9065 80186 : Vector temp;
9066 :
9067 40093 : if (NSides > state.dataSurface->MaxVerticesPerSurface) state.dataSurface->MaxVerticesPerSurface = NSides;
9068 40093 : Ptr = 1;
9069 201160 : for (n = 1; n <= NSides; ++n) {
9070 161067 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x = Vertices(Ptr);
9071 161067 : ++Ptr;
9072 161067 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y = Vertices(Ptr);
9073 161067 : ++Ptr;
9074 161067 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).z = Vertices(Ptr);
9075 161067 : ++Ptr;
9076 : }
9077 :
9078 : // Address changing vertices if they were put in in CW order rather than CCW
9079 40093 : if (!state.dataSurface->CCW) {
9080 : // If even number of sides, this will transfer appropriately
9081 : // If odd number, will leave the "odd" one, which is what you want.
9082 195 : NSrc = NSides;
9083 195 : NTar = 2;
9084 390 : for (n = 1; n <= (NSides - 1) / 2; ++n) {
9085 195 : temp = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(NSrc);
9086 195 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(NSrc) = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(NTar);
9087 195 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(NTar) = temp;
9088 195 : --NSrc;
9089 195 : ++NTar;
9090 : }
9091 : }
9092 : // Now address which "Corner" has been put in first. Note: the azimuth and tilt and area
9093 : // calculations do not care which corner is put in first.
9094 : // 2/2011 - don't think the shading calculations have a corner preference. Will keep this for
9095 : // consistency (for now)
9096 40093 : ThisCorner = state.dataSurface->Corner;
9097 46247 : while (ThisCorner != UpperLeftCorner) {
9098 3077 : if (NSides < 4) {
9099 8 : if (ThisCorner == UpperRightCorner) {
9100 0 : ThisCorner = UpperLeftCorner;
9101 0 : break;
9102 : }
9103 : }
9104 3077 : NTar = ThisCorner;
9105 3077 : NSrc = ThisCorner + 1;
9106 3077 : if (NSrc > NSides) NSrc = 1;
9107 12584 : for (n = 1; n <= NSides - 1; ++n) {
9108 9507 : temp = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(NTar);
9109 9507 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(NTar) = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(NSrc);
9110 9507 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(NSrc) = temp;
9111 9507 : ++NTar;
9112 9507 : ++NSrc;
9113 9507 : if (NTar > NSides) NTar = 1;
9114 9507 : if (NSrc > NSides) NSrc = 1;
9115 : }
9116 3077 : ++ThisCorner;
9117 3077 : if (ThisCorner > NSides) ThisCorner = 1;
9118 : } // Corners
9119 40093 : if (!state.dataSurface->WorldCoordSystem) {
9120 : // Input in "relative" coordinates, use Building and Zone North Axes and Origins
9121 : // to translate each point (including rotation for Appendix G)
9122 31668 : ZoneNum = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone;
9123 31668 : if (ZoneNum > 0) {
9124 158707 : for (n = 1; n <= NSides; ++n) {
9125 381201 : Xb = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x * state.dataSurfaceGeometry->CosZoneRelNorth(ZoneNum) -
9126 127067 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y * state.dataSurfaceGeometry->SinZoneRelNorth(ZoneNum) +
9127 127067 : state.dataHeatBal->Zone(ZoneNum).OriginX;
9128 381201 : Yb = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x * state.dataSurfaceGeometry->SinZoneRelNorth(ZoneNum) +
9129 127067 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y * state.dataSurfaceGeometry->CosZoneRelNorth(ZoneNum) +
9130 127067 : state.dataHeatBal->Zone(ZoneNum).OriginY;
9131 127067 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x =
9132 127067 : Xb * state.dataSurfaceGeometry->CosBldgRelNorth - Yb * state.dataSurfaceGeometry->SinBldgRelNorth;
9133 127067 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y =
9134 127067 : Xb * state.dataSurfaceGeometry->SinBldgRelNorth + Yb * state.dataSurfaceGeometry->CosBldgRelNorth;
9135 127067 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).z += state.dataHeatBal->Zone(ZoneNum).OriginZ;
9136 : }
9137 28 : } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Detached_B) {
9138 62 : for (n = 1; n <= NSides; ++n) {
9139 48 : Xb = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x;
9140 48 : Yb = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y;
9141 48 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x =
9142 48 : Xb * state.dataSurfaceGeometry->CosBldgRelNorth - Yb * state.dataSurfaceGeometry->SinBldgRelNorth;
9143 48 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y =
9144 48 : Xb * state.dataSurfaceGeometry->SinBldgRelNorth + Yb * state.dataSurfaceGeometry->CosBldgRelNorth;
9145 : }
9146 : }
9147 : } else {
9148 : // if world coordinate only need to rotate for Appendix G
9149 8425 : ZoneNum = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone;
9150 8425 : if (ZoneNum > 0) {
9151 42225 : for (n = 1; n <= NSides; ++n) {
9152 33822 : Xb = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x;
9153 33822 : Yb = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y;
9154 33822 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x =
9155 33822 : Xb * state.dataSurfaceGeometry->CosBldgRotAppGonly - Yb * state.dataSurfaceGeometry->SinBldgRotAppGonly;
9156 33822 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y =
9157 33822 : Xb * state.dataSurfaceGeometry->SinBldgRotAppGonly + Yb * state.dataSurfaceGeometry->CosBldgRotAppGonly;
9158 : }
9159 22 : } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Detached_B) {
9160 0 : for (n = 1; n <= NSides; ++n) {
9161 0 : Xb = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x;
9162 0 : Yb = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y;
9163 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x =
9164 0 : Xb * state.dataSurfaceGeometry->CosBldgRotAppGonly - Yb * state.dataSurfaceGeometry->SinBldgRotAppGonly;
9165 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y =
9166 0 : Xb * state.dataSurfaceGeometry->SinBldgRotAppGonly + Yb * state.dataSurfaceGeometry->CosBldgRotAppGonly;
9167 : }
9168 : }
9169 : }
9170 :
9171 40093 : if (NSides > 2) {
9172 40093 : auto &surface = state.dataSurfaceGeometry->SurfaceTmp(SurfNum);
9173 40093 : auto &vertices = surface.Vertex;
9174 40093 : auto &nSides = surface.Sides;
9175 :
9176 40093 : bool poppedVertex = true;
9177 120279 : while (poppedVertex) {
9178 40093 : poppedVertex = false;
9179 40093 : Perimeter = 0.0;
9180 :
9181 201160 : for (auto it = vertices.begin(); it != vertices.end(); ++it) {
9182 161067 : auto itnext = std::next(it);
9183 161067 : if (itnext == std::end(vertices)) {
9184 40093 : itnext = std::begin(vertices);
9185 : }
9186 :
9187 : // TODO: use isAlmostEqual3Pt for consistency? (which uses 0.0127 m / 1/2inch instead of 0.01 m)
9188 161067 : DistanceCheck = distance(*it, *itnext);
9189 161067 : if (DistanceCheck < 0.01) {
9190 0 : int curVertexIndex = std::distance(vertices.begin(), it) + 1;
9191 0 : int nextVertexIndex = std::distance(vertices.begin(), itnext) + 1;
9192 0 : if (state.dataGlobal->DisplayExtraWarnings) {
9193 0 : ShowWarningError(state,
9194 0 : format("{}Distance between two vertices < .01, possibly coincident. for Surface={}, in Zone={}",
9195 : RoutineName,
9196 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name,
9197 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName));
9198 0 : ShowContinueError(state, format("Vertex [{}]=({:.2R},{:.2R},{:.2R})", curVertexIndex, it->x, it->y, it->z));
9199 0 : ShowContinueError(state, format("Vertex [{}]=({:.2R},{:.2R},{:.2R})", nextVertexIndex, itnext->x, itnext->y, it->z));
9200 : }
9201 0 : ++state.dataErrTracking->TotalCoincidentVertices;
9202 0 : if (nSides > 3) {
9203 0 : if (state.dataGlobal->DisplayExtraWarnings) {
9204 0 : ShowContinueError(state, format("Dropping Vertex [{}].", nextVertexIndex));
9205 : }
9206 0 : --nSides;
9207 0 : vertices.erase(itnext);
9208 0 : poppedVertex = true;
9209 0 : break;
9210 : } else {
9211 0 : if (state.dataGlobal->DisplayExtraWarnings) {
9212 0 : ShowContinueError(state,
9213 0 : format("Cannot Drop Vertex [{}]; Number of Surface Sides at minimum. This surface is now a "
9214 : "degenerate surface.",
9215 0 : curVertexIndex));
9216 : }
9217 0 : ++state.dataErrTracking->TotalDegenerateSurfaces;
9218 : // mark degenerate surface?
9219 : }
9220 : } else {
9221 161067 : Perimeter += DistanceCheck;
9222 : }
9223 : }
9224 : }
9225 :
9226 40093 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Perimeter = Perimeter;
9227 :
9228 80186 : CreateNewellSurfaceNormalVector(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
9229 40093 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
9230 40093 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector);
9231 80186 : CreateNewellAreaVector(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
9232 40093 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
9233 40093 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellAreaVector);
9234 : // For surfaces with subsurfaces, the following two areas are turned into net areas later by
9235 : // subtracting subsurface areas
9236 40093 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea = VecLength(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellAreaVector);
9237 40093 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea;
9238 40093 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NetAreaShadowCalc = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area;
9239 240558 : DetermineAzimuthAndTilt(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
9240 40093 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
9241 : SurfWorldAz,
9242 : SurfTilt,
9243 40093 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsx,
9244 40093 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsy,
9245 40093 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsz,
9246 40093 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea,
9247 40093 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector);
9248 40093 : dotp = dot(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector, TestVector);
9249 40093 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Roof && dotp < -0.000001) {
9250 0 : TiltString = format("{:.1R}", SurfTilt);
9251 0 : ShowWarningError(state,
9252 0 : std::string{RoutineName} + "Roof/Ceiling is upside down! Tilt angle=[" + TiltString +
9253 0 : "], should be near 0, Surface=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", in Zone=\"" +
9254 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName + "\".");
9255 0 : ShowContinueError(state, "Automatic fix is attempted.");
9256 0 : ReverseAndRecalculate(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides, SurfWorldAz, SurfTilt);
9257 40093 : } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Roof && SurfTilt > 80.0) {
9258 0 : TiltString = format("{:.1R}", SurfTilt);
9259 0 : ShowWarningError(state,
9260 0 : std::string{RoutineName} + "Roof/Ceiling is not oriented correctly! Tilt angle=[" + TiltString +
9261 0 : "], should be near 0, Surface=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", in Zone=\"" +
9262 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName + "\".");
9263 : }
9264 40093 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Floor && dotp > 0.000001) {
9265 0 : TiltString = format("{:.1R}", SurfTilt);
9266 0 : ShowWarningError(state,
9267 0 : std::string{RoutineName} + "Floor is upside down! Tilt angle=[" + TiltString + "], should be near 180, Surface=\"" +
9268 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", in Zone=\"" +
9269 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName + "\".");
9270 0 : ShowContinueError(state, "Automatic fix is attempted.");
9271 0 : ReverseAndRecalculate(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides, SurfWorldAz, SurfTilt);
9272 40093 : } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Floor && SurfTilt < 158.2) { // slope/grade = 40%!
9273 0 : TiltString = format("{:.1R}", SurfTilt);
9274 0 : ShowWarningError(state,
9275 0 : std::string{RoutineName} + "Floor is not oriented correctly! Tilt angle=[" + TiltString +
9276 0 : "], should be near 180, Surface=\"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", in Zone=\"" +
9277 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName + "\".");
9278 : }
9279 40093 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth = SurfWorldAz;
9280 40093 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt = SurfTilt;
9281 40093 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConvOrientation =
9282 40093 : ConvectionCoefficients::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
9283 :
9284 : // Sine and cosine of azimuth and tilt
9285 40093 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinAzim = std::sin(SurfWorldAz * DataGlobalConstants::DegToRadians);
9286 40093 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosAzim = std::cos(SurfWorldAz * DataGlobalConstants::DegToRadians);
9287 40093 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinTilt = std::sin(SurfTilt * DataGlobalConstants::DegToRadians);
9288 40093 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt = std::cos(SurfTilt * DataGlobalConstants::DegToRadians);
9289 40093 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGround == DataGlobalConstants::AutoCalculate) {
9290 18565 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGround =
9291 18565 : 0.5 * (1.0 - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt);
9292 : }
9293 : // Outward normal unit vector (pointing away from room)
9294 40093 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector;
9295 160372 : for (n = 1; n <= 3; ++n) {
9296 120279 : if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) - 1.0) < 1.e-06)
9297 15097 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) = +1.0;
9298 120279 : if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) + 1.0) < 1.e-06)
9299 17121 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) = -1.0;
9300 120279 : if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n)) < 1.e-06)
9301 72277 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) = 0.0;
9302 : }
9303 :
9304 114870 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Window ||
9305 74273 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::GlassDoor ||
9306 34180 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Door)
9307 6369 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area *= state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier;
9308 : // Can perform tests on this surface here
9309 40093 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSky = 0.5 * (1.0 + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt);
9310 : // The following IR view factors are modified in subr. SkyDifSolarShading if there are shadowing
9311 : // surfaces
9312 40093 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSkyIR = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSky;
9313 40093 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGroundIR = 0.5 * (1.0 - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt);
9314 :
9315 : // Call to transform vertices
9316 :
9317 40093 : TransformVertsByAspect(state, SurfNum, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides);
9318 :
9319 : } else {
9320 0 : ShowFatalError(
9321 0 : state, std::string{RoutineName} + "Called with less than 2 sides, Surface=" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name);
9322 : }
9323 :
9324 : // Preliminary Height/Width
9325 40093 : temp = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(3) - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(2);
9326 40093 : ThisWidth = VecLength(temp);
9327 40093 : temp = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(2) - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(1);
9328 40093 : ThisHeight = VecLength(temp);
9329 40093 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Height = ThisHeight;
9330 40093 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Width = ThisWidth;
9331 40093 : }
9332 :
9333 0 : void ReverseAndRecalculate(EnergyPlusData &state,
9334 : int const SurfNum, // Surface number for the surface
9335 : int const NSides, // number of sides to surface
9336 : Real64 &SurfAzimuth, // Surface Facing angle (will be 0 for roofs/floors)
9337 : Real64 &SurfTilt // Surface tilt (
9338 : )
9339 : {
9340 :
9341 : // SUBROUTINE INFORMATION:
9342 : // AUTHOR Linda Lawrie
9343 : // DATE WRITTEN February 2011
9344 : // MODIFIED na
9345 : // RE-ENGINEERED na
9346 :
9347 : // PURPOSE OF THIS SUBROUTINE:
9348 : // This routine reverses the vertices for a surface (needed when roof/floor is upside down)
9349 : // and recalculates the azimuth, etc for the surface.
9350 :
9351 : // METHODOLOGY EMPLOYED:
9352 : // na
9353 :
9354 : // REFERENCES:
9355 : // na
9356 :
9357 : // Using/Aliasing
9358 : using namespace Vectors;
9359 :
9360 : // SUBROUTINE ARGUMENT DEFINITIONS:
9361 :
9362 : // SUBROUTINE PARAMETER DEFINITIONS:
9363 : static constexpr std::string_view RoutineName("ReverseAndRecalculate: ");
9364 :
9365 : // INTERFACE BLOCK SPECIFICATIONS:
9366 : // na
9367 :
9368 : // DERIVED TYPE DEFINITIONS:
9369 : // na
9370 :
9371 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
9372 : int n; // Loop Control
9373 : int RevPtr; // pointer for reversing vertices
9374 0 : std::string TiltString;
9375 :
9376 : // Object Data
9377 0 : Array1D<Vector> Vertices(NSides); // Vertices, in specified order
9378 :
9379 0 : for (n = 1; n <= NSides; ++n) {
9380 0 : Vertices(n) = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n);
9381 : }
9382 0 : RevPtr = NSides;
9383 0 : for (n = 1; n <= NSides; ++n) {
9384 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n) = Vertices(RevPtr);
9385 0 : --RevPtr;
9386 : }
9387 :
9388 0 : print(state.files.debug, "Reversing Surface Name={}\n", state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name);
9389 0 : for (n = 1; n <= NSides; ++n) {
9390 0 : print(state.files.debug,
9391 : "side={:5} abs coord vertex= {:18.13F} {:18.13F} {:18.13F}\n",
9392 : n,
9393 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x,
9394 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y,
9395 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).z);
9396 : }
9397 :
9398 0 : CreateNewellSurfaceNormalVector(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
9399 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
9400 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector);
9401 0 : DetermineAzimuthAndTilt(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
9402 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
9403 : SurfAzimuth,
9404 : SurfTilt,
9405 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsx,
9406 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsy,
9407 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsz,
9408 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea,
9409 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector);
9410 0 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Roof && SurfTilt > 80.0) {
9411 0 : TiltString = format("{:.1R}", SurfTilt);
9412 0 : ShowWarningError(state,
9413 0 : std::string{RoutineName} + "Roof/Ceiling is still upside down! Tilt angle=[" + TiltString +
9414 : "], should be near 0, please fix manually.");
9415 : }
9416 0 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Floor && SurfTilt < 158.2) { // 40% grade!
9417 0 : ShowWarningError(state,
9418 0 : std::string{RoutineName} + "Floor is still upside down! Tilt angle=[" + TiltString +
9419 : "], should be near 180, please fix manually.");
9420 : }
9421 0 : }
9422 :
9423 771 : void MakeMirrorSurface(EnergyPlusData &state, int &SurfNum) // In=>Surface to Mirror, Out=>new Surface index
9424 : {
9425 :
9426 : // SUBROUTINE INFORMATION:
9427 : // AUTHOR Linda Lawrie
9428 : // DATE WRITTEN June 2002
9429 : // MODIFIED na
9430 : // RE-ENGINEERED na
9431 :
9432 : // PURPOSE OF THIS SUBROUTINE:
9433 : // This subroutine creates a "mirror" surface using the indicated surface.
9434 : // This is the simple approach for bi-directional shading devices. If, perchance,
9435 : // the user has already taken care of this (e.g. fins in middle of wall), there will
9436 : // be extra shading devices shown.
9437 :
9438 : // METHODOLOGY EMPLOYED:
9439 : // Reverse the vertices in the original surface. Add "bi" to name.
9440 :
9441 : using namespace Vectors;
9442 :
9443 : int Vert;
9444 : int NVert;
9445 : Real64 SurfWorldAz;
9446 : Real64 SurfTilt;
9447 : int n;
9448 : // TYPE(Vector) :: temp1
9449 :
9450 771 : NVert = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides;
9451 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).Vertex.allocate(NVert);
9452 : // doesn't work when Vertex are pointers SurfaceTmp(SurfNum+1)=SurfaceTmp(SurfNum)
9453 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).Name = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name;
9454 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).Construction = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction;
9455 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).ConstructionStoredInputValue =
9456 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConstructionStoredInputValue;
9457 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).Class = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class;
9458 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).GrossArea = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea;
9459 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).Area = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area;
9460 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).Azimuth = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth;
9461 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).Height = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Height;
9462 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).Reveal = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Reveal;
9463 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).Shape = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Shape;
9464 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).Sides = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides;
9465 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).Tilt = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt;
9466 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).ConvOrientation =
9467 771 : ConvectionCoefficients::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
9468 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).Width = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Width;
9469 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).HeatTransSurf = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf;
9470 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).BaseSurfName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName;
9471 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).BaseSurf = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf;
9472 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).ZoneName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName;
9473 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).Zone = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone;
9474 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName;
9475 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).ExtBoundCond = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond;
9476 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).ExtSolar = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar;
9477 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).ExtWind = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtWind;
9478 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).ViewFactorGround = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGround;
9479 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).ViewFactorSky = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSky;
9480 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).ViewFactorGroundIR = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGroundIR;
9481 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).ViewFactorSkyIR = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSkyIR;
9482 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).SchedShadowSurfIndex = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex;
9483 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).SchedMinValue = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedMinValue;
9484 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).IsTransparent = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).IsTransparent;
9485 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).activeWindowShadingControl =
9486 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeWindowShadingControl;
9487 1542 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).windowShadingControlList =
9488 1542 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).windowShadingControlList;
9489 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).HasShadeControl = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HasShadeControl;
9490 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).activeShadedConstruction =
9491 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeShadedConstruction;
9492 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).FrameDivider = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider;
9493 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).Multiplier = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier;
9494 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).NetAreaShadowCalc = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NetAreaShadowCalc;
9495 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).Perimeter = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Perimeter;
9496 :
9497 3833 : for (Vert = 1; Vert <= state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides; ++Vert) {
9498 3062 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1).Vertex(Vert) = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(NVert);
9499 3062 : --NVert;
9500 : }
9501 771 : ++SurfNum;
9502 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name = "Mir-" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum - 1).Name;
9503 :
9504 : // TH 3/26/2010
9505 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).MirroredSurf = true;
9506 :
9507 771 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides > 2) {
9508 1542 : CreateNewellAreaVector(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
9509 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
9510 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellAreaVector);
9511 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea = VecLength(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellAreaVector);
9512 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea;
9513 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NetAreaShadowCalc = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area;
9514 1542 : CreateNewellSurfaceNormalVector(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
9515 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
9516 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector);
9517 4626 : DetermineAzimuthAndTilt(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex,
9518 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides,
9519 : SurfWorldAz,
9520 : SurfTilt,
9521 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsx,
9522 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsy,
9523 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsz,
9524 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea,
9525 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector);
9526 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth = SurfWorldAz;
9527 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt = SurfTilt;
9528 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ConvOrientation =
9529 771 : ConvectionCoefficients::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
9530 :
9531 : // Sine and cosine of azimuth and tilt
9532 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinAzim = std::sin(SurfWorldAz * DataGlobalConstants::DegToRadians);
9533 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosAzim = std::cos(SurfWorldAz * DataGlobalConstants::DegToRadians);
9534 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinTilt = std::sin(SurfTilt * DataGlobalConstants::DegToRadians);
9535 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt = std::cos(SurfTilt * DataGlobalConstants::DegToRadians);
9536 : // Outward normal unit vector (pointing away from room)
9537 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellSurfaceNormalVector;
9538 3084 : for (n = 1; n <= 3; ++n) {
9539 2313 : if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) - 1.0) < 1.e-06)
9540 705 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) = +1.0;
9541 2313 : if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) + 1.0) < 1.e-06)
9542 54 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) = -1.0;
9543 2313 : if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n)) < 1.e-06)
9544 1530 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec(n) = 0.0;
9545 : }
9546 :
9547 : // Can perform tests on this surface here
9548 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSky = 0.5 * (1.0 + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt);
9549 : // The following IR view factors are modified in subr. SkyDifSolarShading if there are shadowing
9550 : // surfaces
9551 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSkyIR = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSky;
9552 771 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGroundIR = 0.5 * (1.0 - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt);
9553 : }
9554 771 : }
9555 :
9556 771 : void GetWindowShadingControlData(EnergyPlusData &state, bool &ErrorsFound) // If errors found in input
9557 : {
9558 :
9559 : // SUBROUTINE INFORMATION:
9560 : // AUTHOR Fred Winkelmann
9561 : // DATE WRITTEN November 1998
9562 : // MODIFIED Aug 2001 (FW): add handling of new ShadingControlIsScheduled
9563 : // and GlareControlIsActive fields
9564 : // Nov 2001 (FW): add ShadingDevice as alternative to ShadedConstruction
9565 : // Dec 2001 (FW): add slat angle controls for blinds
9566 : // Aug 2002 (FW): add Setpoint2; check that specified control type is legal
9567 : // Feb 2003 (FW): add error if Material Name of Shading Device is used with
9568 : // Shading Type = BetweenGlassShade or BetweenGlassBlind
9569 : // Dec 2003 (FW): improve BetweenGlassBlind error messages
9570 : // Feb 2009 (BG): improve error checking for OnIfScheduleAllows
9571 : // RE-ENGINEERED na
9572 :
9573 : // PURPOSE OF THIS SUBROUTINE:
9574 : // Reads in the window shading control information
9575 : // from the input data file, interprets it and puts it in the derived type
9576 :
9577 : // Using/Aliasing
9578 : using ScheduleManager::GetScheduleIndex;
9579 :
9580 : // SUBROUTINE PARAMETER DEFINITIONS:
9581 :
9582 771 : int constexpr NumValidShadingTypes(9);
9583 : static Array1D_string const cValidShadingTypes(NumValidShadingTypes,
9584 : {
9585 : "SHADEOFF", // 1
9586 : "INTERIORSHADE", // 2
9587 : "SWITCHABLEGLAZING", // 3
9588 : "EXTERIORSHADE", // 4
9589 : "EXTERIORSCREEN", // 5
9590 : "INTERIORBLIND", // 6
9591 : "EXTERIORBLIND", // 7
9592 : "BETWEENGLASSSHADE", // 8
9593 : "BETWEENGLASSBLIND" // 9
9594 771 : });
9595 :
9596 771 : constexpr std::array<std::string_view, static_cast<int>(WindowShadingControlType::Num)> WindowShadingControlTypeNamesUC{
9597 : "ALWAYSON",
9598 : "ALWAYSOFF",
9599 : "ONIFSCHEDULEALLOWS",
9600 : "ONIFHIGHSOLARONWINDOW",
9601 : "ONIFHIGHHORIZONTALSOLAR",
9602 : "ONIFHIGHOUTDOORAIRTEMPERATURE",
9603 : "ONIFHIGHZONEAIRTEMPERATURE",
9604 : "ONIFHIGHZONECOOLING",
9605 : "ONIFHIGHGLARE",
9606 : "MEETDAYLIGHTILLUMINANCESETPOINT",
9607 : "ONNIGHTIFLOWOUTDOORTEMPANDOFFDAY",
9608 : "ONNIGHTIFLOWINSIDETEMPANDOFFDAY",
9609 : "ONNIGHTIFHEATINGANDOFFDAY",
9610 : "ONNIGHTIFLOWOUTDOORTEMPANDONDAYIFCOOLING",
9611 : "ONNIGHTIFHEATINGANDONDAYIFCOOLING",
9612 : "OFFNIGHTANDONDAYIFCOOLINGANDHIGHSOLARONWINDOW",
9613 : "ONNIGHTANDONDAYIFCOOLINGANDHIGHSOLARONWINDOW",
9614 : "ONIFHIGHOUTDOORAIRTEMPANDHIGHSOLARONWINDOW",
9615 : "ONIFHIGHOUTDOORAIRTEMPANDHIGHHORIZONTALSOLAR",
9616 : "ONIFHIGHZONEAIRTEMPANDHIGHSOLARONWINDOW",
9617 : "ONIFHIGHZONEAIRTEMPANDHIGHHORIZONTALSOLAR",
9618 : "ONIFHIGHSOLARORHIGHLUMINANCETILLMIDNIGHT",
9619 : "ONIFHIGHSOLARORHIGHLUMINANCETILLSUNSET",
9620 : "ONIFHIGHSOLARORHIGHLUMINANCETILLNEXTMORNING"};
9621 :
9622 771 : constexpr std::array<std::string_view, static_cast<int>(SlatAngleControl::Num)> SlatAngleNamesUC{
9623 : "FIXEDSLATANGLE", "SCHEDULEDSLATANGLE", "BLOCKBEAMSOLAR"};
9624 :
9625 771 : constexpr std::array<std::string_view, static_cast<int>(MultiSurfaceControl::Num)> MultiSurfaceControlNamesUC = {"SEQUENTIAL", "GROUP"};
9626 :
9627 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
9628 : int IOStat; // IO Status when calling get input subroutine
9629 : int ControlNumAlpha; // Number of control alpha names being passed
9630 : int ControlNumProp; // Number of control properties being passed
9631 : int ControlNum; // DO loop counter/index for window shading control number
9632 : int IShadedConst; // Construction number of shaded construction
9633 : int IShadingDevice; // Material number of shading device
9634 : int NLayers; // Layers in shaded construction
9635 : bool ErrorInName;
9636 : bool IsBlank;
9637 : int Loop;
9638 : bool BGShadeBlindError; // True if problem with construction that is supposed to have between-glass
9639 : // shade or blind
9640 : int Found;
9641 :
9642 771 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
9643 : // Get the total number of window shading control blocks
9644 771 : cCurrentModuleObject = "WindowShadingControl";
9645 771 : state.dataSurface->TotWinShadingControl = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
9646 771 : if (state.dataSurface->TotWinShadingControl == 0) return;
9647 :
9648 42 : state.dataSurface->WindowShadingControl.allocate(state.dataSurface->TotWinShadingControl);
9649 :
9650 42 : ControlNum = 0;
9651 114 : for (Loop = 1; Loop <= state.dataSurface->TotWinShadingControl; ++Loop) {
9652 :
9653 504 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
9654 : cCurrentModuleObject,
9655 : Loop,
9656 72 : state.dataIPShortCut->cAlphaArgs,
9657 : ControlNumAlpha,
9658 72 : state.dataIPShortCut->rNumericArgs,
9659 : ControlNumProp,
9660 : IOStat,
9661 72 : state.dataIPShortCut->lNumericFieldBlanks,
9662 72 : state.dataIPShortCut->lAlphaFieldBlanks,
9663 72 : state.dataIPShortCut->cAlphaFieldNames,
9664 72 : state.dataIPShortCut->cNumericFieldNames);
9665 :
9666 72 : ErrorInName = false;
9667 72 : IsBlank = false;
9668 144 : UtilityRoutines::VerifyName(state,
9669 72 : state.dataIPShortCut->cAlphaArgs(1),
9670 72 : state.dataSurface->WindowShadingControl,
9671 : ControlNum,
9672 : ErrorInName,
9673 : IsBlank,
9674 144 : cCurrentModuleObject + " Name");
9675 72 : if (ErrorInName) {
9676 0 : ErrorsFound = true;
9677 0 : continue;
9678 : }
9679 :
9680 72 : ++ControlNum;
9681 :
9682 72 : auto &windowShadingControl = state.dataSurface->WindowShadingControl(ControlNum);
9683 :
9684 72 : windowShadingControl.Name = state.dataIPShortCut->cAlphaArgs(1); // Set the Control Name in the Derived Type
9685 :
9686 72 : windowShadingControl.ZoneIndex = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(2), state.dataHeatBal->Zone);
9687 72 : if (windowShadingControl.ZoneIndex == 0) {
9688 0 : ShowSevereError(state,
9689 0 : cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " +
9690 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) + "\" not found.");
9691 0 : ErrorsFound = true;
9692 : }
9693 :
9694 72 : windowShadingControl.SequenceNumber = int(state.dataIPShortCut->rNumericArgs(1));
9695 : // WindowShadingControl().getInputShadedConstruction is only used during GetInput process and is ultimately stored in
9696 : // Surface().shadedConstructionList
9697 216 : windowShadingControl.getInputShadedConstruction = UtilityRoutines::FindItemInList(
9698 216 : state.dataIPShortCut->cAlphaArgs(4), state.dataConstruction->Construct, state.dataHeatBal->TotConstructs);
9699 72 : windowShadingControl.ShadingDevice =
9700 72 : UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(9), state.dataMaterial->Material, state.dataHeatBal->TotMaterials);
9701 72 : windowShadingControl.Schedule = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(6));
9702 72 : windowShadingControl.SetPoint = state.dataIPShortCut->rNumericArgs(2);
9703 72 : windowShadingControl.SetPoint2 = state.dataIPShortCut->rNumericArgs(3);
9704 72 : windowShadingControl.ShadingControlIsScheduled = getYesNoValue(state.dataIPShortCut->cAlphaArgs(7)) == BooleanSwitch::Yes;
9705 72 : windowShadingControl.GlareControlIsActive = getYesNoValue(state.dataIPShortCut->cAlphaArgs(8)) == BooleanSwitch::Yes;
9706 72 : windowShadingControl.SlatAngleSchedule = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(11));
9707 :
9708 : // store the string for now and associate it after daylighting control objects are read
9709 72 : windowShadingControl.DaylightingControlName = state.dataIPShortCut->cAlphaArgs(12);
9710 :
9711 72 : windowShadingControl.multiSurfaceControl = static_cast<MultiSurfaceControl>(
9712 144 : getEnumerationValue(MultiSurfaceControlNamesUC, UtilityRoutines::MakeUPPERCase(state.dataIPShortCut->cAlphaArgs(13))));
9713 :
9714 72 : if (windowShadingControl.multiSurfaceControl == MultiSurfaceControl::Invalid) {
9715 0 : windowShadingControl.multiSurfaceControl = MultiSurfaceControl::Sequential;
9716 0 : ShowWarningError(state,
9717 0 : format("{}=\"{}\" should be either SEQUENTIAL or GROUP {}=\"{}\", defaulting to \"SEQUENTIAL\"",
9718 : cCurrentModuleObject,
9719 : windowShadingControl.Name,
9720 0 : state.dataIPShortCut->cAlphaFieldNames(13),
9721 0 : state.dataIPShortCut->cAlphaArgs(13)));
9722 : }
9723 :
9724 72 : if (ControlNumAlpha >= 14) {
9725 72 : windowShadingControl.FenestrationCount = ControlNumAlpha - 13;
9726 72 : windowShadingControl.FenestrationName.allocate(windowShadingControl.FenestrationCount);
9727 72 : windowShadingControl.FenestrationIndex.allocate(windowShadingControl.FenestrationCount);
9728 219 : for (int i = 1; i <= windowShadingControl.FenestrationCount; i++) {
9729 147 : windowShadingControl.FenestrationName(i) = state.dataIPShortCut->cAlphaArgs(i + 13);
9730 : }
9731 : } else {
9732 0 : ShowSevereError(state,
9733 0 : cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
9734 : "\" invalid. Must reference at least one Fenestration Surface object name.");
9735 : }
9736 :
9737 72 : windowShadingControl.shadingControlType = static_cast<WindowShadingControlType>(
9738 144 : getEnumerationValue(WindowShadingControlTypeNamesUC, UtilityRoutines::MakeUPPERCase(state.dataIPShortCut->cAlphaArgs(5))));
9739 :
9740 72 : if (windowShadingControl.ShadingDevice > 0) {
9741 13 : if (state.dataMaterial->Material(windowShadingControl.ShadingDevice).Group == DataHeatBalance::MaterialGroup::Screen &&
9742 0 : !(windowShadingControl.shadingControlType == WindowShadingControlType::AlwaysOn ||
9743 0 : windowShadingControl.shadingControlType == WindowShadingControlType::AlwaysOff ||
9744 0 : windowShadingControl.shadingControlType == WindowShadingControlType::OnIfScheduled)) {
9745 0 : ErrorsFound = true;
9746 0 : ShowSevereError(state,
9747 0 : cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" invalid " +
9748 0 : state.dataIPShortCut->cAlphaFieldNames(5) + "=\"" + state.dataIPShortCut->cAlphaArgs(5) +
9749 : "\" for exterior screens.");
9750 0 : ShowContinueError(state,
9751 : "Valid shading control types for exterior window screens are ALWAYSON, ALWAYSOFF, or ONIFSCHEDULEALLOWS.");
9752 : }
9753 : } else {
9754 59 : if (windowShadingControl.getInputShadedConstruction > 0) {
9755 59 : state.dataConstruction->Construct(windowShadingControl.getInputShadedConstruction).IsUsed = true;
9756 118 : if (state.dataMaterial->Material(state.dataConstruction->Construct(windowShadingControl.getInputShadedConstruction).LayerPoint(1))
9757 61 : .Group == DataHeatBalance::MaterialGroup::Screen &&
9758 6 : !(windowShadingControl.shadingControlType == WindowShadingControlType::AlwaysOn ||
9759 2 : windowShadingControl.shadingControlType == WindowShadingControlType::AlwaysOff ||
9760 2 : windowShadingControl.shadingControlType == WindowShadingControlType::OnIfScheduled)) {
9761 0 : ErrorsFound = true;
9762 0 : ShowSevereError(state,
9763 0 : cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" invalid " +
9764 0 : state.dataIPShortCut->cAlphaFieldNames(5) + "=\"" + state.dataIPShortCut->cAlphaArgs(5) +
9765 : "\" for exterior screens.");
9766 0 : ShowContinueError(state,
9767 : "Valid shading control types for exterior window screens are ALWAYSON, ALWAYSOFF, or ONIFSCHEDULEALLOWS.");
9768 : }
9769 0 : } else if (state.dataIPShortCut->lAlphaFieldBlanks(4)) {
9770 0 : ShowSevereError(state,
9771 0 : cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\", " + state.dataIPShortCut->cAlphaFieldNames(4) +
9772 : " is blank.");
9773 0 : ShowContinueError(state, "A valid construction is required.");
9774 0 : ErrorsFound = true;
9775 : } else {
9776 0 : ShowSevereError(state,
9777 0 : cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\", " + state.dataIPShortCut->cAlphaFieldNames(4) +
9778 : " is invalid.");
9779 0 : ShowContinueError(state,
9780 0 : "Construction=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\" was used. A valid construction is required.");
9781 0 : ErrorsFound = true;
9782 : }
9783 : }
9784 :
9785 : // Warning if setpoint is unintentionally zero
9786 104 : if (windowShadingControl.SetPoint == 0 && windowShadingControl.shadingControlType != WindowShadingControlType::AlwaysOn &&
9787 64 : windowShadingControl.shadingControlType != WindowShadingControlType::AlwaysOff &&
9788 54 : windowShadingControl.shadingControlType != WindowShadingControlType::OnIfScheduled &&
9789 22 : windowShadingControl.shadingControlType != WindowShadingControlType::HiGlare) {
9790 0 : ShowWarningError(state, cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\", The first SetPoint is zero.");
9791 0 : ShowContinueError(state, "..You may have forgotten to specify that setpoint.");
9792 : }
9793 :
9794 : // Error checks
9795 72 : if (state.dataIPShortCut->cAlphaArgs(7) != "YES" && state.dataIPShortCut->cAlphaArgs(7) != "NO") { // Shading Control is Schedule field
9796 0 : ErrorsFound = true;
9797 0 : ShowSevereError(state,
9798 0 : cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" invalid " + state.dataIPShortCut->cAlphaFieldNames(7) +
9799 0 : "=\"" + state.dataIPShortCut->cAlphaArgs(7) + "\".");
9800 : }
9801 72 : if (state.dataIPShortCut->cAlphaArgs(8) != "YES" && state.dataIPShortCut->cAlphaArgs(8) != "NO") { // Glare Control is Active field
9802 0 : ErrorsFound = true;
9803 0 : ShowSevereError(state,
9804 0 : cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" invalid " + state.dataIPShortCut->cAlphaFieldNames(8) +
9805 0 : "=\"" + state.dataIPShortCut->cAlphaArgs(8) + "\".");
9806 : }
9807 :
9808 84 : if ((windowShadingControl.shadingControlType == WindowShadingControlType::OnIfScheduled) &&
9809 12 : (!windowShadingControl.ShadingControlIsScheduled)) { // CR 7709 BG
9810 0 : ErrorsFound = true;
9811 0 : ShowSevereError(state,
9812 0 : cCurrentModuleObject + " = \"" + windowShadingControl.Name + "\" invalid, " +
9813 0 : state.dataIPShortCut->cAlphaFieldNames(7) + " must be set to \"Yes\" for " +
9814 0 : state.dataIPShortCut->cAlphaFieldNames(5) + " = OnIfScheduleAllows");
9815 : }
9816 72 : windowShadingControl.slatAngleControl = static_cast<SlatAngleControl>(
9817 144 : getEnumerationValue(SlatAngleNamesUC, UtilityRoutines::MakeUPPERCase(state.dataIPShortCut->cAlphaArgs(10))));
9818 :
9819 : // For upward compatibility change old "noninsulating" and "insulating" shade types to
9820 : // INTERIORSHADE or EXTERIORSHADE
9821 144 : if (state.dataIPShortCut->cAlphaArgs(3) == "INTERIORNONINSULATINGSHADE" ||
9822 72 : state.dataIPShortCut->cAlphaArgs(3) == "INTERIORINSULATINGSHADE") {
9823 0 : ShowWarningError(state,
9824 0 : cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" is using obsolete " +
9825 0 : state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) +
9826 : "\", changing to \"InteriorShade\"");
9827 0 : windowShadingControl.ShadingType = WinShadingType::IntShade;
9828 0 : state.dataIPShortCut->cAlphaArgs(3) = "INTERIORSHADE";
9829 : }
9830 144 : if (state.dataIPShortCut->cAlphaArgs(3) == "EXTERIORNONINSULATINGSHADE" ||
9831 72 : state.dataIPShortCut->cAlphaArgs(3) == "EXTERIORINSULATINGSHADE") {
9832 0 : ShowWarningError(state,
9833 0 : cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" is using obsolete " +
9834 0 : state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) +
9835 : "\", changing to \"ExteriorShade\"");
9836 0 : windowShadingControl.ShadingType = WinShadingType::ExtShade;
9837 0 : state.dataIPShortCut->cAlphaArgs(3) = "EXTERIORSHADE";
9838 : }
9839 :
9840 73 : if (windowShadingControl.shadingControlType == WindowShadingControlType::MeetDaylIlumSetp &&
9841 1 : state.dataIPShortCut->cAlphaArgs(3) != "SWITCHABLEGLAZING") {
9842 0 : ErrorsFound = true;
9843 0 : ShowSevereError(state,
9844 0 : cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" invalid " + state.dataIPShortCut->cAlphaFieldNames(3) +
9845 0 : "=\"" + state.dataIPShortCut->cAlphaArgs(3) + "\".");
9846 0 : ShowContinueError(state,
9847 0 : "..." + state.dataIPShortCut->cAlphaFieldNames(3) +
9848 0 : " must be SwitchableGlazing for this control, but entered type=\"" + state.dataIPShortCut->cAlphaArgs(3) +
9849 : "\".");
9850 : }
9851 :
9852 : // Check for illegal shading type name
9853 72 : Found = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(3), cValidShadingTypes, NumValidShadingTypes);
9854 72 : if (Found <= 1) {
9855 0 : ErrorsFound = true;
9856 0 : ShowSevereError(state,
9857 0 : cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" invalid " + state.dataIPShortCut->cAlphaFieldNames(3) +
9858 0 : "=\"" + state.dataIPShortCut->cAlphaArgs(3) + "\".");
9859 : } else {
9860 72 : windowShadingControl.ShadingType = WinShadingType(Found);
9861 : }
9862 :
9863 72 : WinShadingType ShTyp = windowShadingControl.ShadingType;
9864 72 : IShadedConst = windowShadingControl.getInputShadedConstruction;
9865 72 : IShadingDevice = windowShadingControl.ShadingDevice;
9866 :
9867 72 : if (IShadedConst == 0 && IShadingDevice == 0) {
9868 0 : ShowSevereError(
9869 0 : state, cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" has no matching shaded construction or shading device.");
9870 0 : ErrorsFound = true;
9871 72 : } else if (IShadedConst == 0 && IShadingDevice > 0) {
9872 13 : if (ShTyp == WinShadingType::SwitchableGlazing) {
9873 0 : ShowSevereError(state,
9874 0 : cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" has " + state.dataIPShortCut->cAlphaArgs(3) +
9875 : "= SwitchableGlazing but no matching shaded construction");
9876 0 : ErrorsFound = true;
9877 : }
9878 26 : if ((ShTyp == WinShadingType::IntShade || ShTyp == WinShadingType::ExtShade) &&
9879 13 : state.dataMaterial->Material(IShadingDevice).Group != DataHeatBalance::MaterialGroup::Shade) {
9880 0 : ShowSevereError(state,
9881 0 : cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" has " + state.dataIPShortCut->cAlphaArgs(3) +
9882 : "= InteriorShade or ExteriorShade but matching shading device is not a window shade");
9883 0 : ShowContinueError(state,
9884 0 : state.dataIPShortCut->cAlphaFieldNames(8) + " in error=\"" + state.dataMaterial->Material(IShadingDevice).Name +
9885 : "\".");
9886 0 : ErrorsFound = true;
9887 : }
9888 13 : if ((ShTyp == WinShadingType::ExtScreen) &&
9889 0 : state.dataMaterial->Material(IShadingDevice).Group != DataHeatBalance::MaterialGroup::Screen) {
9890 0 : ShowSevereError(state,
9891 0 : cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" has " + state.dataIPShortCut->cAlphaArgs(3) +
9892 : "= ExteriorScreen but matching shading device is not a window screen");
9893 0 : ShowContinueError(state,
9894 0 : state.dataIPShortCut->cAlphaFieldNames(8) + " in error=\"" + state.dataMaterial->Material(IShadingDevice).Name +
9895 : "\".");
9896 0 : ErrorsFound = true;
9897 : }
9898 13 : if ((ShTyp == WinShadingType::IntBlind || ShTyp == WinShadingType::ExtBlind) &&
9899 0 : state.dataMaterial->Material(IShadingDevice).Group != DataHeatBalance::MaterialGroup::WindowBlind) {
9900 0 : ShowSevereError(state,
9901 0 : cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" has " + state.dataIPShortCut->cAlphaArgs(3) +
9902 : "= InteriorBlind or ExteriorBlind but matching shading device is not a window blind");
9903 0 : ShowContinueError(state,
9904 0 : state.dataIPShortCut->cAlphaFieldNames(8) + " in error=\"" + state.dataMaterial->Material(IShadingDevice).Name +
9905 : "\".");
9906 0 : ErrorsFound = true;
9907 : }
9908 26 : if (ShTyp == WinShadingType::BGShade || ShTyp == WinShadingType::BGBlind) {
9909 0 : ShowSevereError(state,
9910 0 : cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" has " + state.dataIPShortCut->cAlphaArgs(3) +
9911 : "= BetweenGlassShade or BetweenGlassBlind and");
9912 0 : ShowContinueError(
9913 0 : state, state.dataIPShortCut->cAlphaFieldNames(8) + " is specified. This is illegal. Specify shaded construction instead.");
9914 0 : ErrorsFound = true;
9915 : }
9916 59 : } else if (IShadedConst > 0 && IShadingDevice > 0) {
9917 0 : IShadingDevice = 0;
9918 0 : ShowWarningError(state,
9919 0 : cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" Both " + state.dataIPShortCut->cAlphaFieldNames(4) +
9920 0 : " and " + state.dataIPShortCut->cAlphaFieldNames(9) + " are specified.");
9921 0 : ShowContinueError(state,
9922 0 : "The " + state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataConstruction->Construct(IShadedConst).Name +
9923 : "\" will be used.");
9924 : }
9925 :
9926 : // If type = interior or exterior shade or blind require that the shaded construction
9927 : // have a shade layer in the correct position
9928 72 : if (IShadedConst != 0) {
9929 :
9930 59 : NLayers = state.dataConstruction->Construct(IShadedConst).TotLayers;
9931 59 : BGShadeBlindError = false;
9932 59 : IShadingDevice = 0;
9933 59 : if (state.dataConstruction->Construct(IShadedConst).LayerPoint(NLayers) != 0) {
9934 59 : if (windowShadingControl.ShadingType == WinShadingType::IntShade) {
9935 10 : IShadingDevice = state.dataConstruction->Construct(IShadedConst).LayerPoint(NLayers);
9936 10 : if (state.dataMaterial->Material(state.dataConstruction->Construct(IShadedConst).LayerPoint(NLayers)).Group !=
9937 : DataHeatBalance::MaterialGroup::Shade) {
9938 0 : ErrorsFound = true;
9939 0 : ShowSevereError(state,
9940 0 : cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" the " +
9941 0 : state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\"");
9942 0 : ShowContinueError(state,
9943 0 : "of " + state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) +
9944 : "\" should have a shade layer on the inside of the window.");
9945 : }
9946 49 : } else if (windowShadingControl.ShadingType == WinShadingType::ExtShade) {
9947 5 : IShadingDevice = state.dataConstruction->Construct(IShadedConst).LayerPoint(1);
9948 5 : if (state.dataMaterial->Material(state.dataConstruction->Construct(IShadedConst).LayerPoint(1)).Group !=
9949 : DataHeatBalance::MaterialGroup::Shade) {
9950 0 : ErrorsFound = true;
9951 0 : ShowSevereError(state,
9952 0 : cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" the " +
9953 0 : state.dataIPShortCut->cAlphaFieldNames(43) + "=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\"");
9954 0 : ShowContinueError(state,
9955 0 : "of " + state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) +
9956 : "\" should have a shade layer on the outside of the window.");
9957 : }
9958 44 : } else if (windowShadingControl.ShadingType == WinShadingType::ExtScreen) {
9959 2 : IShadingDevice = state.dataConstruction->Construct(IShadedConst).LayerPoint(1);
9960 2 : if (state.dataMaterial->Material(state.dataConstruction->Construct(IShadedConst).LayerPoint(1)).Group !=
9961 : DataHeatBalance::MaterialGroup::Screen) {
9962 0 : ErrorsFound = true;
9963 0 : ShowSevereError(state,
9964 0 : cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" the " +
9965 0 : state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\"");
9966 0 : ShowContinueError(state,
9967 0 : "of " + state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) +
9968 : "\" should have a screen layer on the outside of the window.");
9969 : }
9970 42 : } else if (windowShadingControl.ShadingType == WinShadingType::IntBlind) {
9971 12 : IShadingDevice = state.dataConstruction->Construct(IShadedConst).LayerPoint(NLayers);
9972 12 : if (state.dataMaterial->Material(state.dataConstruction->Construct(IShadedConst).LayerPoint(NLayers)).Group !=
9973 : DataHeatBalance::MaterialGroup::WindowBlind) {
9974 0 : ErrorsFound = true;
9975 0 : ShowSevereError(state,
9976 0 : cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" the " +
9977 0 : state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\"");
9978 0 : ShowContinueError(state,
9979 0 : "of " + state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) +
9980 : "\" should have a blind layer on the inside of the window.");
9981 : }
9982 30 : } else if (windowShadingControl.ShadingType == WinShadingType::ExtBlind) {
9983 2 : IShadingDevice = state.dataConstruction->Construct(IShadedConst).LayerPoint(1);
9984 2 : if (state.dataMaterial->Material(state.dataConstruction->Construct(IShadedConst).LayerPoint(1)).Group !=
9985 : DataHeatBalance::MaterialGroup::WindowBlind) {
9986 0 : ErrorsFound = true;
9987 0 : ShowSevereError(state,
9988 0 : cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" the " +
9989 0 : state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\"");
9990 0 : ShowContinueError(state,
9991 0 : "of " + state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) +
9992 : "\" should have a blind layer on the outside of the window.");
9993 : }
9994 28 : } else if (windowShadingControl.ShadingType == WinShadingType::BGShade) {
9995 2 : if (NLayers != 5 && NLayers != 7) BGShadeBlindError = true;
9996 2 : if (NLayers == 5) {
9997 1 : if (state.dataMaterial->Material(state.dataConstruction->Construct(IShadedConst).LayerPoint(3)).Group !=
9998 : DataHeatBalance::MaterialGroup::Shade)
9999 0 : BGShadeBlindError = true;
10000 : }
10001 2 : if (NLayers == 7) {
10002 1 : if (state.dataMaterial->Material(state.dataConstruction->Construct(IShadedConst).LayerPoint(5)).Group !=
10003 : DataHeatBalance::MaterialGroup::Shade)
10004 0 : BGShadeBlindError = true;
10005 : }
10006 2 : if (BGShadeBlindError) {
10007 0 : ErrorsFound = true;
10008 0 : ShowSevereError(state,
10009 0 : cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" the " +
10010 0 : state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\"");
10011 0 : ShowContinueError(state,
10012 0 : "of " + state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(32) +
10013 : "\" should have two or three glass layers and a");
10014 0 : ShowContinueError(state, "between-glass shade layer with a gas layer on each side.");
10015 : }
10016 26 : } else if (windowShadingControl.ShadingType == WinShadingType::BGBlind) {
10017 3 : if (NLayers != 5 && NLayers != 7) BGShadeBlindError = true;
10018 3 : if (NLayers == 5) {
10019 2 : if (state.dataMaterial->Material(state.dataConstruction->Construct(IShadedConst).LayerPoint(3)).Group !=
10020 : DataHeatBalance::MaterialGroup::WindowBlind)
10021 0 : BGShadeBlindError = true;
10022 : }
10023 3 : if (NLayers == 7) {
10024 1 : if (state.dataMaterial->Material(state.dataConstruction->Construct(IShadedConst).LayerPoint(5)).Group !=
10025 : DataHeatBalance::MaterialGroup::WindowBlind)
10026 0 : BGShadeBlindError = true;
10027 : }
10028 3 : if (BGShadeBlindError) {
10029 0 : ErrorsFound = true;
10030 0 : ShowSevereError(state,
10031 0 : cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" the " +
10032 0 : state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\"");
10033 0 : ShowContinueError(state,
10034 0 : "of " + state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) +
10035 : "\" should have two or three glass layers and a");
10036 0 : ShowContinueError(state, "between-glass blind layer with a gas layer on each side.");
10037 : }
10038 : }
10039 : }
10040 59 : if (IShadingDevice > 0) {
10041 46 : if ((ShTyp == WinShadingType::IntShade || ShTyp == WinShadingType::ExtShade) &&
10042 15 : state.dataMaterial->Material(IShadingDevice).Group != DataHeatBalance::MaterialGroup::Shade) {
10043 0 : ShowSevereError(state,
10044 0 : cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" has " +
10045 0 : state.dataIPShortCut->cAlphaFieldNames(3) +
10046 : "= InteriorShade or ExteriorShade but matching shading device is not a window shade");
10047 0 : ShowContinueError(state, "Shading Device in error=\"" + state.dataMaterial->Material(IShadingDevice).Name + "\".");
10048 0 : ErrorsFound = true;
10049 : }
10050 33 : if ((ShTyp == WinShadingType::ExtScreen) &&
10051 2 : state.dataMaterial->Material(IShadingDevice).Group != DataHeatBalance::MaterialGroup::Screen) {
10052 0 : ShowSevereError(state,
10053 0 : cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" has " +
10054 0 : state.dataIPShortCut->cAlphaFieldNames(3) +
10055 : "= ExteriorScreen but matching shading device is not an exterior window screen.");
10056 0 : ShowContinueError(state, "Shading Device in error=\"" + state.dataMaterial->Material(IShadingDevice).Name + "\".");
10057 0 : ErrorsFound = true;
10058 : }
10059 45 : if ((ShTyp == WinShadingType::IntBlind || ShTyp == WinShadingType::ExtBlind) &&
10060 14 : state.dataMaterial->Material(IShadingDevice).Group != DataHeatBalance::MaterialGroup::WindowBlind) {
10061 0 : ShowSevereError(state,
10062 0 : cCurrentModuleObject + "=\"" + windowShadingControl.Name + "\" has " +
10063 0 : state.dataIPShortCut->cAlphaFieldNames(3) +
10064 : "= InteriorBlind or ExteriorBlind but matching shading device is not a window blind.");
10065 0 : ShowContinueError(state, "Shading Device in error=\"" + state.dataMaterial->Material(IShadingDevice).Name + "\".");
10066 0 : ErrorsFound = true;
10067 : }
10068 : }
10069 : }
10070 : } // End of loop over window shading controls
10071 : }
10072 :
10073 5982 : void InitialAssociateWindowShadingControlFenestration(EnergyPlusData &state, bool &ErrorsFound, int &SurfNum)
10074 : {
10075 : // J.Glazer 2018 - operates on SurfaceTmp array before final indices are known for windows and sets the activeWindowShadingControl
10076 7663 : for (int iShadeCtrl = 1; iShadeCtrl <= state.dataSurface->TotWinShadingControl; ++iShadeCtrl) {
10077 1681 : int curShadedConstruction = state.dataSurface->WindowShadingControl(iShadeCtrl).getInputShadedConstruction;
10078 6591 : for (int jFeneRef = 1; jFeneRef <= state.dataSurface->WindowShadingControl(iShadeCtrl).FenestrationCount; ++jFeneRef) {
10079 4910 : if (UtilityRoutines::SameString(state.dataSurface->WindowShadingControl(iShadeCtrl).FenestrationName(jFeneRef),
10080 4910 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name)) {
10081 147 : state.dataGlobal->AndShadingControlInModel = true;
10082 147 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HasShadeControl = true;
10083 147 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).windowShadingControlList.push_back(iShadeCtrl);
10084 147 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeWindowShadingControl = iShadeCtrl;
10085 147 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).shadedConstructionList.push_back(curShadedConstruction);
10086 147 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeShadedConstruction = curShadedConstruction;
10087 :
10088 : // check to make the window refenced is an exterior window
10089 147 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond != ExternalEnvironment) {
10090 0 : ErrorsFound = true;
10091 0 : ShowSevereError(state,
10092 0 : "InitialAssociateWindowShadingControlFenestration: \"" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
10093 0 : "\", invalid " + " because it is not an exterior window.");
10094 0 : ShowContinueError(
10095 0 : state, ".. It appears on WindowShadingControl object: \"" + state.dataSurface->WindowShadingControl(iShadeCtrl).Name);
10096 : }
10097 : // check to make sure the window is not using equivalent layer window construction
10098 147 : if (state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).WindowTypeEQL) {
10099 0 : ErrorsFound = true;
10100 0 : ShowSevereError(state,
10101 0 : "InitialAssociateWindowShadingControlFenestration: =\"" +
10102 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + "\", invalid " + "\".");
10103 0 : ShowContinueError(state, ".. equivalent layer window model does not use shading control object.");
10104 0 : ShowContinueError(state, ".. Shading control is set to none or zero, and simulation continues.");
10105 0 : ShowContinueError(
10106 0 : state, ".. It appears on WindowShadingControl object: \"" + state.dataSurface->WindowShadingControl(iShadeCtrl).Name);
10107 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeWindowShadingControl = 0;
10108 : }
10109 : }
10110 : }
10111 : }
10112 5982 : }
10113 :
10114 43762 : void FinalAssociateWindowShadingControlFenestration(EnergyPlusData &state, bool &ErrorsFound)
10115 : {
10116 : // J.Glazer 2018 - operates on Surface array after final indices are known for windows and checks to make sure it is correct
10117 51402 : for (int iShadeCtrl = 1; iShadeCtrl <= state.dataSurface->TotWinShadingControl; ++iShadeCtrl) {
10118 25527 : for (int jFeneRef = 1; jFeneRef <= state.dataSurface->WindowShadingControl(iShadeCtrl).FenestrationCount; ++jFeneRef) {
10119 : int fenestrationIndex =
10120 35774 : UtilityRoutines::FindItemInList(state.dataSurface->WindowShadingControl(iShadeCtrl).FenestrationName(jFeneRef),
10121 17887 : state.dataSurface->Surface,
10122 35774 : state.dataSurface->TotSurfaces);
10123 53661 : if (std::find(state.dataSurface->Surface(fenestrationIndex).windowShadingControlList.begin(),
10124 35774 : state.dataSurface->Surface(fenestrationIndex).windowShadingControlList.end(),
10125 53661 : iShadeCtrl) != state.dataSurface->Surface(fenestrationIndex).windowShadingControlList.end()) {
10126 17887 : state.dataSurface->WindowShadingControl(iShadeCtrl).FenestrationIndex(jFeneRef) = fenestrationIndex;
10127 : } else {
10128 : // this error condition should not occur since the rearrangement of Surface() from SurfureTmp() is reliable.
10129 0 : ErrorsFound = true;
10130 0 : ShowSevereError(state,
10131 0 : "FinalAssociateWindowShadingControlFenestration: Fenestration surface named \"" +
10132 0 : state.dataSurface->Surface(fenestrationIndex).Name +
10133 : "\" has WindowShadingContol index that does not match the initial index assigned.");
10134 0 : ShowContinueError(state,
10135 0 : "This occurs while WindowShadingControl object: \"" + state.dataSurface->WindowShadingControl(iShadeCtrl).Name +
10136 : "\" is being evaluated. ");
10137 : }
10138 : }
10139 : }
10140 43762 : }
10141 :
10142 43762 : void CheckWindowShadingControlSimilarForWindow(EnergyPlusData &state, bool &ErrorsFound)
10143 : {
10144 : // For each window check if all window shading controls on list are the same except for name, schedule name, construction, and
10145 : // material
10146 11618580 : for (auto &theSurf : state.dataSurface->Surface) {
10147 11574818 : if (theSurf.HasShadeControl) {
10148 17747 : if (theSurf.windowShadingControlList.size() > 1) {
10149 140 : int firstWindowShadingControl = theSurf.windowShadingControlList.front();
10150 280 : for (auto wsc = std::next(theSurf.windowShadingControlList.begin()); wsc != theSurf.windowShadingControlList.end(); ++wsc) {
10151 140 : if (!isWindowShadingControlSimilar(state, firstWindowShadingControl, *wsc)) {
10152 0 : ErrorsFound = true;
10153 0 : ShowSevereError(state,
10154 0 : "CheckWindowShadingControlSimilarForWindow: Fenestration surface named \"" + theSurf.Name +
10155 : "\" has multiple WindowShadingContols that are not similar.");
10156 0 : ShowContinueError(state,
10157 0 : "for: \"" + state.dataSurface->WindowShadingControl(firstWindowShadingControl).Name +
10158 0 : " and: " + state.dataSurface->WindowShadingControl(*wsc).Name);
10159 : }
10160 : }
10161 : }
10162 : }
10163 : }
10164 43762 : }
10165 :
10166 140 : bool isWindowShadingControlSimilar(EnergyPlusData &state, int a, int b)
10167 : {
10168 : // Compares two window shading controls are the same except for the name, schedule name, construction, and material
10169 140 : auto &WindowShadingControlA(state.dataSurface->WindowShadingControl(a));
10170 140 : auto &WindowShadingControlB(state.dataSurface->WindowShadingControl(b));
10171 280 : return (WindowShadingControlA.ZoneIndex == WindowShadingControlB.ZoneIndex &&
10172 280 : WindowShadingControlA.ShadingType == WindowShadingControlB.ShadingType &&
10173 280 : WindowShadingControlA.shadingControlType == WindowShadingControlB.shadingControlType &&
10174 280 : WindowShadingControlA.SetPoint == WindowShadingControlB.SetPoint &&
10175 280 : WindowShadingControlA.ShadingControlIsScheduled == WindowShadingControlB.ShadingControlIsScheduled &&
10176 280 : WindowShadingControlA.GlareControlIsActive == WindowShadingControlB.GlareControlIsActive &&
10177 280 : WindowShadingControlA.slatAngleControl == WindowShadingControlB.slatAngleControl &&
10178 280 : WindowShadingControlA.SetPoint2 == WindowShadingControlB.SetPoint2 &&
10179 280 : WindowShadingControlA.DaylightingControlName == WindowShadingControlB.DaylightingControlName &&
10180 420 : WindowShadingControlA.DaylightControlIndex == WindowShadingControlB.DaylightControlIndex &&
10181 280 : WindowShadingControlA.multiSurfaceControl == WindowShadingControlB.multiSurfaceControl);
10182 : }
10183 :
10184 771 : void GetStormWindowData(EnergyPlusData &state, bool &ErrorsFound) // If errors found in input
10185 : {
10186 :
10187 : // SUBROUTINE INFORMATION:
10188 : // AUTHOR Fred Winkelmann
10189 : // DATE WRITTEN December 2003
10190 : // MODIFIED na
10191 :
10192 : // RE-ENGINEERED na
10193 :
10194 : // PURPOSE OF THIS SUBROUTINE:
10195 : // Reads in the storm window data from the input file,
10196 : // interprets it and puts it in the derived type
10197 :
10198 : // Using/Aliasing
10199 :
10200 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
10201 :
10202 : int IOStat; // IO Status when calling get input subroutine
10203 : int StormWinNumAlpha; // Number of alpha names being passed
10204 : int StormWinNumProp; // Number of properties being passed
10205 : int StormWinNum; // Index for storm window number
10206 : int loop; // Do loop counter
10207 : int SurfNum; // Surface number
10208 : int MatNum; // Material number
10209 :
10210 771 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
10211 :
10212 : // Get the total number of storm window input objects
10213 771 : cCurrentModuleObject = "WindowProperty:StormWindow";
10214 771 : state.dataSurface->TotStormWin = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
10215 771 : if (state.dataSurface->TotStormWin == 0) return;
10216 :
10217 1 : state.dataSurface->StormWindow.allocate(state.dataSurface->TotStormWin);
10218 :
10219 1 : StormWinNum = 0;
10220 1 : for (loop = 1; loop <= state.dataSurface->TotStormWin; ++loop) {
10221 :
10222 7 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
10223 : cCurrentModuleObject,
10224 : loop,
10225 1 : state.dataIPShortCut->cAlphaArgs,
10226 : StormWinNumAlpha,
10227 1 : state.dataIPShortCut->rNumericArgs,
10228 : StormWinNumProp,
10229 : IOStat,
10230 1 : state.dataIPShortCut->lNumericFieldBlanks,
10231 1 : state.dataIPShortCut->lAlphaFieldBlanks,
10232 1 : state.dataIPShortCut->cAlphaFieldNames,
10233 1 : state.dataIPShortCut->cNumericFieldNames);
10234 1 : ++StormWinNum;
10235 1 : state.dataSurface->StormWindow(StormWinNum).BaseWindowNum =
10236 1 : UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(1), state.dataSurface->Surface, state.dataSurface->TotSurfaces);
10237 1 : state.dataSurface->StormWindow(StormWinNum).StormWinMaterialNum =
10238 1 : UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(2), state.dataMaterial->Material, state.dataHeatBal->TotMaterials);
10239 1 : state.dataSurface->StormWindow(StormWinNum).StormWinDistance = state.dataIPShortCut->rNumericArgs(1);
10240 1 : state.dataSurface->StormWindow(StormWinNum).MonthOn = state.dataIPShortCut->rNumericArgs(2);
10241 1 : state.dataSurface->StormWindow(StormWinNum).DayOfMonthOn = state.dataIPShortCut->rNumericArgs(3);
10242 1 : state.dataSurface->StormWindow(StormWinNum).DateOn =
10243 1 : General::OrdinalDay(state.dataSurface->StormWindow(StormWinNum).MonthOn, state.dataSurface->StormWindow(StormWinNum).DayOfMonthOn, 1);
10244 1 : state.dataSurface->StormWindow(StormWinNum).MonthOff = state.dataIPShortCut->rNumericArgs(4);
10245 1 : state.dataSurface->StormWindow(StormWinNum).DayOfMonthOff = state.dataIPShortCut->rNumericArgs(5);
10246 2 : state.dataSurface->StormWindow(StormWinNum).DateOff = General::OrdinalDay(
10247 2 : state.dataSurface->StormWindow(StormWinNum).MonthOff, state.dataSurface->StormWindow(StormWinNum).DayOfMonthOff, 1);
10248 :
10249 1 : if (state.dataSurface->StormWindow(StormWinNum).DateOn == state.dataSurface->StormWindow(StormWinNum).DateOff) {
10250 0 : ShowSevereError(state,
10251 0 : format("{}: Date On = Date Off -- not allowed, occurred in WindowProperty:StormWindow Input #{}",
10252 : cCurrentModuleObject,
10253 0 : StormWinNum));
10254 0 : ErrorsFound = true;
10255 : }
10256 :
10257 : enum Month
10258 : {
10259 : January = 1,
10260 : February,
10261 : March,
10262 : April,
10263 : May,
10264 : June,
10265 : July,
10266 : August,
10267 : September,
10268 : October,
10269 : November,
10270 : December
10271 : };
10272 1 : constexpr std::array<int, 13> oneBasedDaysInMonth = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
10273 :
10274 1 : int const monthOn = state.dataSurface->StormWindow(StormWinNum).MonthOn;
10275 1 : if (monthOn >= January && monthOn <= December) {
10276 2 : if (state.dataSurface->StormWindow(StormWinNum).DayOfMonthOn >
10277 1 : oneBasedDaysInMonth[state.dataSurface->StormWindow(StormWinNum).MonthOn]) {
10278 0 : ShowSevereError(state,
10279 0 : format("{}: Date On (Day of Month) [{}], invalid for WindowProperty:StormWindow Input #{}",
10280 : cCurrentModuleObject,
10281 0 : state.dataSurface->StormWindow(StormWinNum).DayOfMonthOn,
10282 0 : StormWinNum));
10283 0 : ErrorsFound = true;
10284 : }
10285 2 : break;
10286 : } else {
10287 0 : ShowSevereError(state,
10288 0 : format("{}: Date On Month [{}], invalid for WindowProperty:StormWindow Input #{}",
10289 : cCurrentModuleObject,
10290 0 : state.dataSurface->StormWindow(StormWinNum).MonthOn,
10291 0 : StormWinNum));
10292 0 : ErrorsFound = true;
10293 : }
10294 :
10295 0 : int const monthOff = state.dataSurface->StormWindow(StormWinNum).MonthOff;
10296 0 : if (monthOff >= January && monthOff <= December) {
10297 0 : if (state.dataSurface->StormWindow(StormWinNum).DayOfMonthOff >
10298 0 : oneBasedDaysInMonth[state.dataSurface->StormWindow(StormWinNum).MonthOff]) {
10299 0 : ShowSevereError(state,
10300 0 : format("{}: Date Off (Day of Month) [{}], invalid for WindowProperty:StormWindow Input #{}",
10301 : cCurrentModuleObject,
10302 0 : state.dataSurface->StormWindow(StormWinNum).DayOfMonthOff,
10303 0 : StormWinNum));
10304 0 : ErrorsFound = true;
10305 : }
10306 0 : break;
10307 : } else {
10308 0 : ShowSevereError(state,
10309 0 : format("{}: Date Off Month [{}], invalid for WindowProperty:StormWindow Input #{}",
10310 : cCurrentModuleObject,
10311 0 : state.dataSurface->StormWindow(StormWinNum).MonthOff,
10312 0 : StormWinNum));
10313 0 : ErrorsFound = true;
10314 : }
10315 : }
10316 :
10317 : // Error checks
10318 :
10319 2 : for (StormWinNum = 1; StormWinNum <= state.dataSurface->TotStormWin; ++StormWinNum) {
10320 : // Require BaseWindowNum be that of an exterior window
10321 1 : SurfNum = state.dataSurface->StormWindow(StormWinNum).BaseWindowNum;
10322 1 : if (SurfNum == 0) {
10323 0 : ShowSevereError(state, cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid.");
10324 0 : ErrorsFound = true;
10325 : } else {
10326 1 : if (state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Window || state.dataSurface->Surface(SurfNum).ExtBoundCond != 0) {
10327 0 : ShowSevereError(state, cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\"");
10328 0 : ShowSevereError(state, "cannot be used with surface=" + state.dataSurface->Surface(SurfNum).Name);
10329 0 : ShowContinueError(state, "because that surface is not an exterior window.");
10330 0 : ErrorsFound = true;
10331 : }
10332 : }
10333 :
10334 : // Require that storm window material be glass
10335 1 : MatNum = state.dataSurface->StormWindow(StormWinNum).StormWinMaterialNum;
10336 1 : if (SurfNum > 0) {
10337 1 : if (MatNum == 0) {
10338 0 : ShowSevereError(state, cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\"");
10339 0 : ShowContinueError(state,
10340 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) +
10341 : "\" not found as storm window layer.");
10342 0 : ErrorsFound = true;
10343 : } else {
10344 1 : if (state.dataMaterial->Material(MatNum).Group != DataHeatBalance::MaterialGroup::WindowGlass) {
10345 0 : ShowSevereError(state, cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\"");
10346 0 : ShowContinueError(state,
10347 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) +
10348 : "must be a WindowMaterial:Glazing or WindowMaterial:Glazing:RefractionExtinctionMethod");
10349 0 : ErrorsFound = true;
10350 : }
10351 : }
10352 : }
10353 :
10354 : // Error if base window has airflow control
10355 1 : if (SurfNum > 0) {
10356 1 : if (state.dataSurface->SurfWinAirflowControlType(SurfNum) != DataSurfaces::WindowAirFlowControlType::Invalid) {
10357 0 : ShowSevereError(
10358 : state,
10359 0 : format("{}=\"{} cannot be used because it is an airflow window (i.e., has WindowProperty:AirflowControl specified)",
10360 : cCurrentModuleObject,
10361 0 : state.dataIPShortCut->cAlphaArgs(1)));
10362 0 : ErrorsFound = true;
10363 : }
10364 : }
10365 :
10366 : // Check for reversal of on and off times
10367 1 : if (SurfNum > 0) {
10368 3 : if ((state.dataEnvrn->Latitude > 0.0 &&
10369 2 : (state.dataSurface->StormWindow(StormWinNum).MonthOn < state.dataSurface->StormWindow(StormWinNum).MonthOff)) ||
10370 1 : (state.dataEnvrn->Latitude <= 0.0 &&
10371 0 : (state.dataSurface->StormWindow(StormWinNum).MonthOn > state.dataSurface->StormWindow(StormWinNum).MonthOff))) {
10372 0 : ShowWarningError(state, cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" check times that storm window");
10373 0 : ShowContinueError(state,
10374 0 : format("is put on (month={}, day={}) and taken off (month={}, day={});",
10375 0 : state.dataSurface->StormWindow(StormWinNum).MonthOn,
10376 0 : state.dataSurface->StormWindow(StormWinNum).DayOfMonthOn,
10377 0 : state.dataSurface->StormWindow(StormWinNum).MonthOff,
10378 0 : state.dataSurface->StormWindow(StormWinNum).DayOfMonthOff));
10379 0 : ShowContinueError(state, format("these times may be reversed for your building latitude={:.2R} deg.", state.dataEnvrn->Latitude));
10380 : }
10381 : }
10382 : }
10383 : }
10384 :
10385 771 : void GetWindowGapAirflowControlData(EnergyPlusData &state, bool &ErrorsFound) // If errors found in input
10386 : {
10387 :
10388 : // SUBROUTINE INFORMATION:
10389 : // AUTHOR Fred Winkelmann
10390 : // DATE WRITTEN Feb 2003
10391 : // MODIFIED June 2003, FCW: add destination = return air;
10392 : // more error messages
10393 : // RE-ENGINEERED na
10394 :
10395 : // PURPOSE OF THIS SUBROUTINE:
10396 : // Reads in the window airflow control information from the input data file,
10397 : // interprets it and puts it in the SurfaceWindow derived type
10398 :
10399 : // Using/Aliasing
10400 : using ScheduleManager::GetScheduleIndex;
10401 :
10402 : static constexpr std::string_view RoutineName("GetWindowGapAirflowControlData");
10403 : int IOStat; // IO Status when calling get input subroutine
10404 : int ControlNumAlpha; // Number of control alpha names being passed
10405 : int ControlNumProp; // Number of control properties being passed
10406 : int TotWinAirflowControl; // Total window airflow control statements
10407 : bool WrongSurfaceType; // True if associated surface is not 2- or 3-pane exterior window
10408 : int Loop;
10409 : int SurfNum; // Surface number
10410 771 : int ConstrNum(0); // Construction number
10411 : int ConstrNumSh; // Shaded Construction number
10412 : int MatGapFlow; // Material number of gas in airflow gap of window's construction
10413 : int MatGapFlow1; // Material number of gas on either side of a between-glass shade/blind
10414 : int MatGapFlow2;
10415 :
10416 771 : constexpr std::array<std::string_view, static_cast<int>(WindowAirFlowSource::Num)> WindowAirFlowSourceNamesUC{"INDOORAIR", "OUTDOORAIR"};
10417 771 : constexpr std::array<std::string_view, static_cast<int>(WindowAirFlowDestination::Num)> WindowAirFlowDestinationNamesUC{
10418 : "INDOORAIR", "OUTDOORAIR", "RETURNAIR"};
10419 :
10420 : // of the shaded construction of airflow window
10421 771 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
10422 : // Get the total number of window airflow control statements
10423 771 : cCurrentModuleObject = "WindowProperty:AirflowControl";
10424 771 : TotWinAirflowControl = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
10425 771 : if (TotWinAirflowControl == 0) return;
10426 :
10427 10 : for (Loop = 1; Loop <= TotWinAirflowControl; ++Loop) { // Loop through all surfaces in the input...
10428 :
10429 56 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
10430 : cCurrentModuleObject,
10431 : Loop,
10432 8 : state.dataIPShortCut->cAlphaArgs,
10433 : ControlNumAlpha,
10434 8 : state.dataIPShortCut->rNumericArgs,
10435 : ControlNumProp,
10436 : IOStat,
10437 8 : state.dataIPShortCut->lNumericFieldBlanks,
10438 8 : state.dataIPShortCut->lAlphaFieldBlanks,
10439 8 : state.dataIPShortCut->cAlphaFieldNames,
10440 8 : state.dataIPShortCut->cNumericFieldNames);
10441 :
10442 8 : SurfNum =
10443 8 : UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(1), state.dataSurface->Surface, state.dataSurface->TotSurfaces);
10444 8 : if (SurfNum == 0) {
10445 0 : ShowSevereError(state, cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" not found.");
10446 0 : ErrorsFound = true;
10447 : }
10448 : // Check that associated surface is a 2- or 3-pane exterior window
10449 8 : WrongSurfaceType = false;
10450 8 : if (SurfNum != 0) {
10451 8 : if (state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Window) WrongSurfaceType = true;
10452 8 : if (state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Window) {
10453 8 : ConstrNum = state.dataSurface->Surface(SurfNum).Construction;
10454 12 : if (state.dataConstruction->Construct(ConstrNum).TotGlassLayers != 2 &&
10455 4 : state.dataConstruction->Construct(ConstrNum).TotGlassLayers != 3)
10456 0 : WrongSurfaceType = true;
10457 8 : if (state.dataSurface->Surface(SurfNum).ExtBoundCond != ExternalEnvironment) WrongSurfaceType = true;
10458 : }
10459 8 : if (WrongSurfaceType) {
10460 0 : ShowSevereError(state,
10461 0 : cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
10462 : "\" is not an exterior window with 2 or 3 glass layers.");
10463 0 : ErrorsFound = true;
10464 : }
10465 : }
10466 :
10467 : // Error if illegal airflow source
10468 8 : if (state.dataIPShortCut->cAlphaArgs(2) != "INDOORAIR" && state.dataIPShortCut->cAlphaArgs(2) != "OUTDOORAIR") {
10469 0 : ErrorsFound = true;
10470 0 : ShowSevereError(state,
10471 0 : cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " +
10472 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) + "\"");
10473 : }
10474 :
10475 : // Error if illegal airflow destination
10476 8 : if (state.dataIPShortCut->cAlphaArgs(3) != "INDOORAIR" && state.dataIPShortCut->cAlphaArgs(3) != "OUTDOORAIR" &&
10477 0 : state.dataIPShortCut->cAlphaArgs(3) != "RETURNAIR") {
10478 0 : ErrorsFound = true;
10479 0 : ShowSevereError(state,
10480 0 : cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " +
10481 0 : state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) + "\"");
10482 : }
10483 :
10484 : // Error if source = OutsideAir and destination = ReturnAir
10485 8 : if (state.dataIPShortCut->cAlphaArgs(2) == "OUTDOORAIR" && state.dataIPShortCut->cAlphaArgs(3) == "RETURNAIR") {
10486 0 : ErrorsFound = true;
10487 0 : ShowSevereError(state,
10488 0 : cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " +
10489 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) + "\"");
10490 0 : ShowContinueError(state, "..when " + state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) + "\"");
10491 : }
10492 :
10493 : // Error if illegal airflow control type
10494 8 : if (state.dataIPShortCut->cAlphaArgs(4) != "ALWAYSONATMAXIMUMFLOW" && state.dataIPShortCut->cAlphaArgs(4) != "ALWAYSOFF" &&
10495 0 : state.dataIPShortCut->cAlphaArgs(4) != "SCHEDULEDONLY") {
10496 0 : ErrorsFound = true;
10497 0 : ShowSevereError(state,
10498 0 : cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " +
10499 0 : state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\"");
10500 : }
10501 :
10502 : // Error if illegal value for Airflow Has Multiplier Schedule
10503 8 : if (state.dataIPShortCut->cAlphaArgs(5) != "YES" && state.dataIPShortCut->cAlphaArgs(5) != "NO") {
10504 0 : ErrorsFound = true;
10505 0 : ShowSevereError(state,
10506 0 : cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " +
10507 0 : state.dataIPShortCut->cAlphaFieldNames(5) + "=\"" + state.dataIPShortCut->cAlphaArgs(5) + "\"");
10508 : }
10509 :
10510 : // Error if Airflow Control Type = ScheduledOnly and Airflow Has Multiplier Schedule = No
10511 8 : if (state.dataIPShortCut->cAlphaArgs(4) == "SCHEDULEDONLY" && state.dataIPShortCut->cAlphaArgs(5) == "NO") {
10512 0 : ErrorsFound = true;
10513 0 : ShowSevereError(state,
10514 0 : cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " +
10515 0 : state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\"");
10516 0 : ShowContinueError(state, "..when " + state.dataIPShortCut->cAlphaFieldNames(5) + "=\"" + state.dataIPShortCut->cAlphaArgs(5) + "\"");
10517 : }
10518 :
10519 : // Warning if Airflow Control Type = AlwaysOnAtMaxFlow and Airflow Has Multiplier Schedule = Yes
10520 8 : if (state.dataIPShortCut->cAlphaArgs(4) == "ALWAYSONATMAXIMUMFLOW" && state.dataIPShortCut->cAlphaArgs(5) == "YES") {
10521 0 : ShowWarningError(state,
10522 0 : cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "has " +
10523 0 : state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\"");
10524 0 : ShowContinueError(state,
10525 0 : "..but " + state.dataIPShortCut->cAlphaFieldNames(5) + "=\"" + state.dataIPShortCut->cAlphaArgs(5) +
10526 0 : "If specified, the " + state.dataIPShortCut->cAlphaFieldNames(5) + " will be ignored.");
10527 : }
10528 :
10529 : // Warning if Airflow Control Type = AlwaysOff and Airflow Has Multiplier Schedule = Yes
10530 8 : if (state.dataIPShortCut->cAlphaArgs(4) == "ALWAYSOFF" && state.dataIPShortCut->cAlphaArgs(5) == "YES") {
10531 0 : ShowWarningError(state,
10532 0 : cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "has " +
10533 0 : state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\"");
10534 0 : ShowContinueError(state,
10535 0 : "..but " + state.dataIPShortCut->cAlphaFieldNames(5) + "=\"" + state.dataIPShortCut->cAlphaArgs(5) +
10536 0 : "\". If specified, the " + state.dataIPShortCut->cAlphaFieldNames(5) + " will be ignored.");
10537 : }
10538 :
10539 8 : if (SurfNum > 0) {
10540 8 : state.dataSurface->AirflowWindows = true;
10541 8 : state.dataSurface->SurfWinAirflowSource(SurfNum) =
10542 16 : static_cast<WindowAirFlowSource>(getEnumerationValue(WindowAirFlowSourceNamesUC, state.dataIPShortCut->cAlphaArgs(2)));
10543 :
10544 8 : state.dataSurface->SurfWinAirflowDestination(SurfNum) =
10545 16 : static_cast<WindowAirFlowDestination>(getEnumerationValue(WindowAirFlowDestinationNamesUC, state.dataIPShortCut->cAlphaArgs(3)));
10546 :
10547 8 : if (state.dataSurface->SurfWinAirflowDestination(SurfNum) == WindowAirFlowDestination::Return) {
10548 0 : int controlledZoneNum = DataZoneEquipment::GetControlledZoneIndex(state, state.dataSurface->Surface(SurfNum).ZoneName);
10549 0 : if (controlledZoneNum > 0) {
10550 0 : state.dataHeatBal->Zone(state.dataSurface->Surface(SurfNum).Zone).HasAirFlowWindowReturn = true;
10551 : }
10552 :
10553 : // Set return air node number
10554 0 : state.dataSurface->SurfWinAirflowReturnNodePtr(SurfNum) = 0;
10555 0 : std::string retNodeName = "";
10556 0 : if (!state.dataIPShortCut->lAlphaFieldBlanks(7)) {
10557 0 : retNodeName = state.dataIPShortCut->cAlphaArgs(7);
10558 : }
10559 0 : std::string callDescription = cCurrentModuleObject + "=" + state.dataSurface->Surface(SurfNum).Name;
10560 0 : state.dataSurface->SurfWinAirflowReturnNodePtr(SurfNum) =
10561 0 : DataZoneEquipment::GetReturnAirNodeForZone(state, state.dataSurface->Surface(SurfNum).Zone, retNodeName, callDescription);
10562 0 : if (state.dataSurface->SurfWinAirflowReturnNodePtr(SurfNum) == 0) {
10563 0 : ShowSevereError(state,
10564 0 : std::string{RoutineName} + cCurrentModuleObject + "=\"" + state.dataSurface->Surface(SurfNum).Name +
10565 0 : "\", airflow window return air node not found for " + state.dataIPShortCut->cAlphaFieldNames(3) + " = " +
10566 0 : state.dataIPShortCut->cAlphaArgs(3));
10567 0 : if (!state.dataIPShortCut->lAlphaFieldBlanks(7))
10568 0 : ShowContinueError(state,
10569 0 : state.dataIPShortCut->cAlphaFieldNames(7) + "=\"" + state.dataIPShortCut->cAlphaArgs(7) +
10570 : "\" did not find a matching return air node.");
10571 0 : ShowContinueError(state,
10572 : "..Airflow windows with Airflow Destination = ReturnAir must reference a controlled Zone (appear in a "
10573 : "ZoneHVAC:EquipmentConnections object) with at least one return air node.");
10574 0 : ErrorsFound = true;
10575 : }
10576 : }
10577 8 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(4), "AlwaysOnAtMaximumFlow")) {
10578 8 : state.dataSurface->SurfWinAirflowControlType(SurfNum) = WindowAirFlowControlType::MaxFlow;
10579 0 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(4), "AlwaysOff")) {
10580 0 : state.dataSurface->SurfWinAirflowControlType(SurfNum) = WindowAirFlowControlType::AlwaysOff;
10581 0 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(4), "ScheduledOnly")) {
10582 0 : state.dataSurface->SurfWinAirflowControlType(SurfNum) = WindowAirFlowControlType::Schedule;
10583 : }
10584 8 : state.dataSurface->SurfWinMaxAirflow(SurfNum) = state.dataIPShortCut->rNumericArgs(1);
10585 8 : if (state.dataIPShortCut->cAlphaArgs(4) == "SCHEDULEDONLY" && state.dataIPShortCut->cAlphaArgs(5) == "YES") {
10586 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(6)) {
10587 0 : ErrorsFound = true;
10588 0 : ShowSevereError(state,
10589 0 : cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", has " +
10590 0 : state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\"");
10591 0 : ShowContinueError(state,
10592 0 : "..and " + state.dataIPShortCut->cAlphaFieldNames(5) + "=\"" + state.dataIPShortCut->cAlphaArgs(5) +
10593 0 : "\", but no " + state.dataIPShortCut->cAlphaFieldNames(6) + " specified.");
10594 : } else {
10595 0 : state.dataSurface->SurfWinAirflowHasSchedule(SurfNum) = true;
10596 0 : state.dataSurface->SurfWinAirflowSchedulePtr(SurfNum) = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(6));
10597 0 : if (state.dataSurface->SurfWinAirflowSchedulePtr(SurfNum) == 0) {
10598 0 : ErrorsFound = true;
10599 0 : ShowSevereError(state,
10600 0 : cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", invalid " +
10601 0 : state.dataIPShortCut->cAlphaFieldNames(6) + "=\"" + state.dataIPShortCut->cAlphaArgs(6) + "\"");
10602 : }
10603 : }
10604 : }
10605 : // Warning if associated window is an interior window
10606 8 : if (state.dataSurface->Surface(SurfNum).ExtBoundCond != ExternalEnvironment && !ErrorsFound)
10607 0 : ShowWarningError(state,
10608 0 : cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
10609 : "\", is an Interior window; cannot be an airflow window.");
10610 8 : if (!ErrorsFound) {
10611 : // Require that gas in airflow gap has type = air
10612 8 : MatGapFlow = state.dataConstruction->Construct(ConstrNum).LayerPoint(2);
10613 8 : if (state.dataConstruction->Construct(ConstrNum).TotGlassLayers == 3)
10614 4 : MatGapFlow = state.dataConstruction->Construct(ConstrNum).LayerPoint(4);
10615 8 : if (state.dataMaterial->Material(MatGapFlow).GasType(1) != 1) {
10616 0 : ErrorsFound = true;
10617 0 : ShowSevereError(state,
10618 0 : cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
10619 0 : "\", Gas type not air in airflow gap of construction " +
10620 0 : state.dataConstruction->Construct(ConstrNum).Name);
10621 : }
10622 : // Require that gas be air in airflow gaps on either side of a between glass shade/blind
10623 8 : if (state.dataSurface->Surface(SurfNum).HasShadeControl) {
10624 4 : for (std::size_t listIndex = 0; listIndex < state.dataSurface->Surface(SurfNum).windowShadingControlList.size();
10625 : ++listIndex) {
10626 4 : int WSCPtr = state.dataSurface->Surface(SurfNum).windowShadingControlList[listIndex];
10627 4 : if (ANY_BETWEENGLASS_SHADE_BLIND(state.dataSurface->WindowShadingControl(WSCPtr).ShadingType)) {
10628 4 : ConstrNumSh = state.dataSurface->Surface(SurfNum).shadedConstructionList[listIndex];
10629 4 : if (state.dataConstruction->Construct(ConstrNum).TotGlassLayers == 2) {
10630 2 : MatGapFlow1 = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(2);
10631 2 : MatGapFlow2 = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(4);
10632 : } else {
10633 2 : MatGapFlow1 = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(4);
10634 2 : MatGapFlow2 = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(6);
10635 : }
10636 8 : if (state.dataMaterial->Material(MatGapFlow1).GasType(1) != 1 ||
10637 4 : state.dataMaterial->Material(MatGapFlow2).GasType(1) != 1) {
10638 0 : ErrorsFound = true;
10639 0 : ShowSevereError(state,
10640 0 : cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
10641 : "\", gas type must be air on either side of the shade/blind");
10642 : }
10643 4 : break; // only need the first window shading control since they should be the same
10644 : }
10645 : }
10646 : }
10647 : }
10648 : }
10649 :
10650 : } // End of loop over window airflow controls
10651 : }
10652 :
10653 771 : void GetFoundationData(EnergyPlusData &state, bool &ErrorsFound)
10654 : {
10655 :
10656 : int NumAlphas;
10657 : int NumProps;
10658 : int IOStat;
10659 771 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
10660 :
10661 : // Read Kiva Settings
10662 771 : cCurrentModuleObject = "Foundation:Kiva:Settings";
10663 771 : int TotKivaStgs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
10664 :
10665 771 : if (TotKivaStgs > 1) {
10666 0 : ErrorsFound = true;
10667 0 : ShowSevereError(state, "Multiple " + cCurrentModuleObject + " objects found. Only one is allowed.");
10668 : }
10669 :
10670 771 : if (TotKivaStgs == 1) {
10671 35 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
10672 : cCurrentModuleObject,
10673 : 1,
10674 5 : state.dataIPShortCut->cAlphaArgs,
10675 : NumAlphas,
10676 5 : state.dataIPShortCut->rNumericArgs,
10677 : NumProps,
10678 : IOStat,
10679 5 : state.dataIPShortCut->lNumericFieldBlanks,
10680 5 : state.dataIPShortCut->lAlphaFieldBlanks,
10681 5 : state.dataIPShortCut->cAlphaFieldNames,
10682 5 : state.dataIPShortCut->cNumericFieldNames);
10683 :
10684 5 : int numF = 1;
10685 5 : int alpF = 1;
10686 :
10687 5 : if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
10688 5 : state.dataSurfaceGeometry->kivaManager.settings.soilK = state.dataIPShortCut->rNumericArgs(numF);
10689 : }
10690 5 : numF++;
10691 5 : if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
10692 5 : state.dataSurfaceGeometry->kivaManager.settings.soilRho = state.dataIPShortCut->rNumericArgs(numF);
10693 : }
10694 5 : numF++;
10695 5 : if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
10696 5 : state.dataSurfaceGeometry->kivaManager.settings.soilCp = state.dataIPShortCut->rNumericArgs(numF);
10697 : }
10698 5 : numF++;
10699 5 : if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
10700 5 : state.dataSurfaceGeometry->kivaManager.settings.groundSolarAbs = state.dataIPShortCut->rNumericArgs(numF);
10701 : }
10702 5 : numF++;
10703 5 : if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
10704 5 : state.dataSurfaceGeometry->kivaManager.settings.groundThermalAbs = state.dataIPShortCut->rNumericArgs(numF);
10705 : }
10706 5 : numF++;
10707 5 : if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
10708 5 : state.dataSurfaceGeometry->kivaManager.settings.groundRoughness = state.dataIPShortCut->rNumericArgs(numF);
10709 : }
10710 5 : numF++;
10711 5 : if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
10712 5 : state.dataSurfaceGeometry->kivaManager.settings.farFieldWidth = state.dataIPShortCut->rNumericArgs(numF);
10713 : }
10714 5 : numF++;
10715 :
10716 5 : if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF)) {
10717 5 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(alpF), "ZeroFlux")) {
10718 1 : state.dataSurfaceGeometry->kivaManager.settings.deepGroundBoundary = HeatBalanceKivaManager::KivaManager::Settings::ZERO_FLUX;
10719 4 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(alpF), "GroundWater")) {
10720 0 : state.dataSurfaceGeometry->kivaManager.settings.deepGroundBoundary = HeatBalanceKivaManager::KivaManager::Settings::GROUNDWATER;
10721 4 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(alpF), "Autoselect")) {
10722 4 : state.dataSurfaceGeometry->kivaManager.settings.deepGroundBoundary = HeatBalanceKivaManager::KivaManager::Settings::AUTO;
10723 : } else {
10724 0 : ErrorsFound = true;
10725 0 : ShowSevereError(state,
10726 0 : format("{}, {} is not a valid choice for {}",
10727 : cCurrentModuleObject,
10728 0 : state.dataIPShortCut->cAlphaArgs(alpF),
10729 0 : state.dataIPShortCut->cAlphaFieldNames(alpF)));
10730 : }
10731 : }
10732 5 : alpF++;
10733 :
10734 5 : if (state.dataIPShortCut->lNumericFieldBlanks(numF) || state.dataIPShortCut->rNumericArgs(numF) == DataGlobalConstants::AutoCalculate) {
10735 : // Autocalculate deep-ground depth (see KivaManager::defineDefaultFoundation() for actual calculation)
10736 4 : state.dataSurfaceGeometry->kivaManager.settings.deepGroundDepth = 40.0;
10737 4 : state.dataSurfaceGeometry->kivaManager.settings.autocalculateDeepGroundDepth = true;
10738 4 : if (state.dataSurfaceGeometry->kivaManager.settings.deepGroundBoundary != HeatBalanceKivaManager::KivaManager::Settings::AUTO) {
10739 0 : ErrorsFound = true;
10740 0 : ShowSevereError(state,
10741 0 : format("{}, {} should not be set to Autocalculate unless {} is set to Autoselect",
10742 : cCurrentModuleObject,
10743 0 : state.dataIPShortCut->cNumericFieldNames(numF),
10744 0 : state.dataIPShortCut->cAlphaFieldNames(alpF - 1)));
10745 : }
10746 : } else {
10747 1 : state.dataSurfaceGeometry->kivaManager.settings.deepGroundDepth = state.dataIPShortCut->rNumericArgs(numF);
10748 1 : state.dataSurfaceGeometry->kivaManager.settings.autocalculateDeepGroundDepth = false;
10749 : }
10750 5 : numF++;
10751 5 : if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
10752 1 : state.dataSurfaceGeometry->kivaManager.settings.minCellDim = state.dataIPShortCut->rNumericArgs(numF);
10753 : }
10754 5 : numF++;
10755 5 : if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
10756 1 : state.dataSurfaceGeometry->kivaManager.settings.maxGrowthCoeff = state.dataIPShortCut->rNumericArgs(numF);
10757 : }
10758 5 : numF++;
10759 :
10760 5 : if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF)) {
10761 1 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(alpF), "Hourly")) {
10762 1 : state.dataSurfaceGeometry->kivaManager.settings.timestepType = HeatBalanceKivaManager::KivaManager::Settings::HOURLY;
10763 1 : state.dataSurfaceGeometry->kivaManager.timestep = 3600.; // seconds
10764 : } else { // if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs( alpF ), "Timestep"))
10765 0 : state.dataSurfaceGeometry->kivaManager.settings.timestepType = HeatBalanceKivaManager::KivaManager::Settings::TIMESTEP;
10766 0 : state.dataSurfaceGeometry->kivaManager.timestep = state.dataGlobal->MinutesPerTimeStep * 60.;
10767 : }
10768 : }
10769 5 : alpF++;
10770 : }
10771 :
10772 : // Set default foundation (probably doesn't need to be called if there are no Kiva
10773 : // surfaces, but we don't know that yet). We call this here so that the default
10774 : // foundation is available for 1) the starting copy for user-defined Foundation:Kiva
10775 : // object default inputs, and 2) the actual default Foundation object if a
10776 : // user-defined Foundation:Kiva name is not referenced by a surface.
10777 771 : state.dataSurfaceGeometry->kivaManager.defineDefaultFoundation(state);
10778 :
10779 : // Read Foundation objects
10780 771 : cCurrentModuleObject = "Foundation:Kiva";
10781 771 : int TotKivaFnds = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
10782 :
10783 771 : if (TotKivaFnds > 0) {
10784 14 : for (int Loop = 1; Loop <= TotKivaFnds; ++Loop) {
10785 49 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
10786 : cCurrentModuleObject,
10787 : Loop,
10788 7 : state.dataIPShortCut->cAlphaArgs,
10789 : NumAlphas,
10790 7 : state.dataIPShortCut->rNumericArgs,
10791 : NumProps,
10792 : IOStat,
10793 7 : state.dataIPShortCut->lNumericFieldBlanks,
10794 7 : state.dataIPShortCut->lAlphaFieldBlanks,
10795 7 : state.dataIPShortCut->cAlphaFieldNames,
10796 7 : state.dataIPShortCut->cNumericFieldNames);
10797 :
10798 7 : int numF = 1;
10799 7 : int alpF = 1;
10800 :
10801 7 : bool ErrorInName = false;
10802 :
10803 14 : HeatBalanceKivaManager::FoundationKiva fndInput;
10804 :
10805 7 : fndInput.name = state.dataIPShortCut->cAlphaArgs(alpF);
10806 7 : alpF++;
10807 7 : UtilityRoutines::IsNameEmpty(state, fndInput.name, cCurrentModuleObject, ErrorInName);
10808 7 : if (ErrorInName) {
10809 0 : ErrorsFound = true;
10810 0 : continue;
10811 : }
10812 :
10813 : // Start with copy of default
10814 7 : auto &fnd = fndInput.foundation;
10815 7 : fnd = state.dataSurfaceGeometry->kivaManager.defaultFoundation.foundation;
10816 :
10817 : // Indoor temperature
10818 7 : if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
10819 1 : fndInput.assumedIndoorTemperature = state.dataIPShortCut->rNumericArgs(numF);
10820 : } else {
10821 6 : fndInput.assumedIndoorTemperature = -9999;
10822 : }
10823 7 : numF++;
10824 :
10825 : // Interior horizontal insulation
10826 7 : if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF)) {
10827 3 : int index = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(alpF), state.dataMaterial->Material);
10828 3 : if (index == 0) {
10829 0 : ErrorsFound = true;
10830 0 : ShowSevereError(state,
10831 0 : "Did not find matching material for " + cCurrentModuleObject + "=\"" + fndInput.name + "\", " +
10832 0 : state.dataIPShortCut->cAlphaFieldNames(alpF) +
10833 0 : ", missing material = " + state.dataIPShortCut->cAlphaArgs(alpF));
10834 0 : continue;
10835 : }
10836 3 : auto &m = state.dataMaterial->Material(index);
10837 3 : if (m.Group != DataHeatBalance::MaterialGroup::RegularMaterial || m.ROnly) {
10838 0 : ErrorsFound = true;
10839 0 : ShowSevereError(state,
10840 0 : cCurrentModuleObject + "=\"" + fndInput.name + "\", invalid " + state.dataIPShortCut->cAlphaFieldNames(alpF) +
10841 0 : "=\"" + state.dataIPShortCut->cAlphaArgs(alpF));
10842 0 : ShowContinueError(state, "Must be of type \"Material\"");
10843 0 : continue;
10844 : }
10845 3 : fndInput.intHIns.x = 0.0;
10846 3 : fndInput.intHIns.material = Kiva::Material(m.Conductivity, m.Density, m.SpecHeat);
10847 3 : fndInput.intHIns.depth = m.Thickness;
10848 : }
10849 7 : alpF++;
10850 :
10851 7 : if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF - 1)) {
10852 3 : if (state.dataIPShortCut->lNumericFieldBlanks(numF)) {
10853 3 : fndInput.intHIns.z = 0.0;
10854 : } else {
10855 0 : fndInput.intHIns.z = state.dataIPShortCut->rNumericArgs(numF);
10856 : }
10857 3 : numF++;
10858 3 : if (state.dataIPShortCut->lNumericFieldBlanks(numF)) {
10859 0 : ErrorsFound = true;
10860 0 : ShowSevereError(state,
10861 0 : cCurrentModuleObject + "=\"" + fndInput.name + "\", " + state.dataIPShortCut->cAlphaFieldNames(alpF - 1) +
10862 0 : " defined, but no " + state.dataIPShortCut->cNumericFieldNames(numF) + "provided");
10863 0 : continue;
10864 : } else {
10865 3 : fndInput.intHIns.width = -state.dataIPShortCut->rNumericArgs(numF);
10866 : }
10867 3 : numF++;
10868 : } else {
10869 4 : if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
10870 0 : ShowWarningError(state,
10871 0 : cCurrentModuleObject + "=\"" + fndInput.name + "\", no " + state.dataIPShortCut->cAlphaFieldNames(alpF - 1) +
10872 : " defined");
10873 0 : ShowContinueError(state, state.dataIPShortCut->cNumericFieldNames(numF) + " will not be used.");
10874 : }
10875 4 : numF++;
10876 4 : if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
10877 0 : ShowWarningError(state,
10878 0 : cCurrentModuleObject + "=\"" + fndInput.name + "\", no " + state.dataIPShortCut->cAlphaFieldNames(alpF - 1) +
10879 : " defined");
10880 0 : ShowContinueError(state, state.dataIPShortCut->cNumericFieldNames(numF) + " will not be used.");
10881 : }
10882 4 : numF++;
10883 : }
10884 :
10885 : // Interior vertical insulation
10886 7 : if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF)) {
10887 0 : int index = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(alpF), state.dataMaterial->Material);
10888 0 : if (index == 0) {
10889 0 : ErrorsFound = true;
10890 0 : ShowSevereError(state,
10891 0 : "Did not find matching material for " + cCurrentModuleObject + "=\"" + fndInput.name + "\", " +
10892 0 : state.dataIPShortCut->cAlphaFieldNames(alpF) +
10893 0 : ", missing material = " + state.dataIPShortCut->cAlphaArgs(alpF));
10894 0 : continue;
10895 : }
10896 0 : auto &m = state.dataMaterial->Material(index);
10897 0 : if (m.Group != DataHeatBalance::MaterialGroup::RegularMaterial || m.ROnly) {
10898 0 : ErrorsFound = true;
10899 0 : ShowSevereError(state,
10900 0 : cCurrentModuleObject + "=\"" + fndInput.name + "\", invalid " + state.dataIPShortCut->cAlphaFieldNames(alpF) +
10901 0 : "=\"" + state.dataIPShortCut->cAlphaArgs(alpF));
10902 0 : ShowContinueError(state, "Must be of type \"Material\"");
10903 0 : continue;
10904 : }
10905 0 : fndInput.intVIns.material = Kiva::Material(m.Conductivity, m.Density, m.SpecHeat);
10906 0 : fndInput.intVIns.width = -m.Thickness;
10907 0 : fndInput.intVIns.x = 0.0;
10908 0 : fndInput.intVIns.z = 0.0;
10909 : }
10910 7 : alpF++;
10911 :
10912 7 : if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF - 1)) {
10913 0 : if (state.dataIPShortCut->lNumericFieldBlanks(numF)) {
10914 0 : ErrorsFound = true;
10915 0 : ShowSevereError(state,
10916 0 : cCurrentModuleObject + "=\"" + fndInput.name + "\", " + state.dataIPShortCut->cAlphaFieldNames(alpF - 1) +
10917 0 : " defined, but no " + state.dataIPShortCut->cNumericFieldNames(numF) + "provided");
10918 0 : continue;
10919 : } else {
10920 0 : fndInput.intVIns.depth = state.dataIPShortCut->rNumericArgs(numF);
10921 : }
10922 0 : numF++;
10923 : } else {
10924 7 : if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
10925 0 : ShowWarningError(state,
10926 0 : cCurrentModuleObject + "=\"" + fndInput.name + "\", no " + state.dataIPShortCut->cAlphaFieldNames(alpF - 1) +
10927 : " defined");
10928 0 : ShowContinueError(state, state.dataIPShortCut->cNumericFieldNames(numF) + " will not be used.");
10929 : }
10930 7 : numF++;
10931 : }
10932 :
10933 : // Exterior horizontal insulation
10934 7 : if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF)) {
10935 0 : int index = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(alpF), state.dataMaterial->Material);
10936 0 : if (index == 0) {
10937 0 : ErrorsFound = true;
10938 0 : ShowSevereError(state,
10939 0 : "Did not find matching material for " + cCurrentModuleObject + "=\"" + fndInput.name + "\", " +
10940 0 : state.dataIPShortCut->cAlphaFieldNames(alpF) +
10941 0 : ", missing material = " + state.dataIPShortCut->cAlphaArgs(alpF));
10942 0 : continue;
10943 : }
10944 0 : auto &m = state.dataMaterial->Material(index);
10945 0 : if (m.Group != DataHeatBalance::MaterialGroup::RegularMaterial || m.ROnly) {
10946 0 : ErrorsFound = true;
10947 0 : ShowSevereError(state,
10948 0 : cCurrentModuleObject + "=\"" + fndInput.name + "\", invalid " + state.dataIPShortCut->cAlphaFieldNames(alpF) +
10949 0 : "=\"" + state.dataIPShortCut->cAlphaArgs(alpF));
10950 0 : ShowContinueError(state, "Must be of type \"Material\"");
10951 0 : continue;
10952 : }
10953 0 : fndInput.extHIns.x = 0.0;
10954 0 : fndInput.extHIns.material = Kiva::Material(m.Conductivity, m.Density, m.SpecHeat);
10955 0 : fndInput.extHIns.depth = m.Thickness;
10956 : }
10957 7 : alpF++;
10958 :
10959 7 : if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF - 1)) {
10960 0 : if (state.dataIPShortCut->lNumericFieldBlanks(numF)) {
10961 0 : fndInput.extHIns.z = 0.0;
10962 : } else {
10963 0 : fndInput.extHIns.z = state.dataIPShortCut->rNumericArgs(numF);
10964 : }
10965 0 : numF++;
10966 0 : if (state.dataIPShortCut->lNumericFieldBlanks(numF)) {
10967 0 : ErrorsFound = true;
10968 0 : ShowSevereError(state,
10969 0 : cCurrentModuleObject + "=\"" + fndInput.name + "\", " + state.dataIPShortCut->cAlphaFieldNames(alpF - 1) +
10970 0 : " defined, but no " + state.dataIPShortCut->cNumericFieldNames(numF) + "provided");
10971 0 : continue;
10972 : } else {
10973 0 : fndInput.extHIns.width = state.dataIPShortCut->rNumericArgs(numF);
10974 : }
10975 0 : numF++;
10976 : } else {
10977 7 : if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
10978 0 : ShowWarningError(state,
10979 0 : cCurrentModuleObject + "=\"" + fndInput.name + "\", no " + state.dataIPShortCut->cAlphaFieldNames(alpF - 1) +
10980 : " defined");
10981 0 : ShowContinueError(state, state.dataIPShortCut->cNumericFieldNames(numF) + " will not be used.");
10982 : }
10983 7 : numF++;
10984 7 : if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
10985 0 : ShowWarningError(state,
10986 0 : cCurrentModuleObject + "=\"" + fndInput.name + "\", no " + state.dataIPShortCut->cAlphaFieldNames(alpF - 1) +
10987 : " defined");
10988 0 : ShowContinueError(state, state.dataIPShortCut->cNumericFieldNames(numF) + " will not be used.");
10989 : }
10990 7 : numF++;
10991 : }
10992 :
10993 : // Exterior vertical insulation
10994 7 : if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF)) {
10995 4 : int index = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(alpF), state.dataMaterial->Material);
10996 4 : if (index == 0) {
10997 0 : ErrorsFound = true;
10998 0 : ShowSevereError(state,
10999 0 : "Did not find matching material for " + cCurrentModuleObject + "=\"" + fndInput.name + "\", " +
11000 0 : state.dataIPShortCut->cAlphaFieldNames(alpF) +
11001 0 : ", missing material = " + state.dataIPShortCut->cAlphaArgs(alpF));
11002 0 : continue;
11003 : }
11004 4 : auto &m = state.dataMaterial->Material(index);
11005 4 : if (m.Group != DataHeatBalance::MaterialGroup::RegularMaterial || m.ROnly) {
11006 0 : ErrorsFound = true;
11007 0 : ShowSevereError(state,
11008 0 : cCurrentModuleObject + "=\"" + fndInput.name + "\", invalid " + state.dataIPShortCut->cAlphaFieldNames(alpF) +
11009 0 : "=\"" + state.dataIPShortCut->cAlphaArgs(alpF));
11010 0 : ShowContinueError(state, "Must be of type \"Material\"");
11011 0 : continue;
11012 : }
11013 4 : fndInput.extVIns.material = Kiva::Material(m.Conductivity, m.Density, m.SpecHeat);
11014 4 : fndInput.extVIns.width = m.Thickness;
11015 4 : fndInput.extVIns.x = 0.0;
11016 4 : fndInput.extVIns.z = 0.0;
11017 : }
11018 7 : alpF++;
11019 :
11020 7 : if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF - 1)) {
11021 4 : if (state.dataIPShortCut->lNumericFieldBlanks(numF)) {
11022 0 : ErrorsFound = true;
11023 0 : ShowSevereError(state,
11024 0 : cCurrentModuleObject + "=\"" + fndInput.name + "\", " + state.dataIPShortCut->cAlphaFieldNames(alpF - 1) +
11025 0 : " defined, but no " + state.dataIPShortCut->cNumericFieldNames(numF) + "provided");
11026 0 : continue;
11027 : } else {
11028 4 : fndInput.extVIns.depth = state.dataIPShortCut->rNumericArgs(numF);
11029 : }
11030 4 : numF++;
11031 : } else {
11032 3 : if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
11033 0 : ShowWarningError(state,
11034 0 : cCurrentModuleObject + "=\"" + fndInput.name + "\", no " + state.dataIPShortCut->cAlphaFieldNames(alpF - 1) +
11035 : " defined");
11036 0 : ShowContinueError(state, state.dataIPShortCut->cNumericFieldNames(numF) + " will not be used.");
11037 : }
11038 3 : numF++;
11039 : }
11040 :
11041 : // Foundation wall
11042 7 : if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
11043 7 : fnd.wall.heightAboveGrade = state.dataIPShortCut->rNumericArgs(numF);
11044 : }
11045 7 : numF++;
11046 :
11047 7 : if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
11048 7 : fnd.wall.depthBelowSlab = state.dataIPShortCut->rNumericArgs(numF);
11049 : }
11050 7 : numF++;
11051 :
11052 7 : if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF)) {
11053 0 : fndInput.wallConstructionIndex =
11054 0 : UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(alpF), state.dataConstruction->Construct);
11055 0 : if (fndInput.wallConstructionIndex == 0) {
11056 0 : ErrorsFound = true;
11057 0 : ShowSevereError(state,
11058 0 : "Did not find matching construction for " + cCurrentModuleObject + "=\"" + fndInput.name + "\", " +
11059 0 : state.dataIPShortCut->cAlphaFieldNames(alpF) +
11060 0 : ", missing construction = " + state.dataIPShortCut->cAlphaArgs(alpF));
11061 0 : continue;
11062 : }
11063 0 : auto &c = state.dataConstruction->Construct(fndInput.wallConstructionIndex);
11064 0 : c.IsUsed = true;
11065 0 : if (c.TypeIsWindow) {
11066 0 : ErrorsFound = true;
11067 0 : ShowSevereError(state,
11068 0 : cCurrentModuleObject + "=\"" + fndInput.name + "\", invalid " + state.dataIPShortCut->cAlphaFieldNames(alpF) +
11069 0 : "=\"" + state.dataIPShortCut->cAlphaArgs(alpF));
11070 0 : ShowContinueError(state, "Cannot be a window construction");
11071 0 : continue;
11072 : }
11073 : } else {
11074 7 : fndInput.wallConstructionIndex = 0; // Use default wall construction
11075 : }
11076 7 : alpF++;
11077 :
11078 : // Footing
11079 7 : if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF)) {
11080 0 : int index = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(alpF), state.dataMaterial->Material);
11081 0 : if (index == 0) {
11082 0 : ErrorsFound = true;
11083 0 : ShowSevereError(state,
11084 0 : "Did not find matching material for " + cCurrentModuleObject + "=\"" + fndInput.name + "\", " +
11085 0 : state.dataIPShortCut->cAlphaFieldNames(alpF) +
11086 0 : ", missing material = " + state.dataIPShortCut->cAlphaArgs(alpF));
11087 0 : continue;
11088 : }
11089 0 : auto &m = state.dataMaterial->Material(index);
11090 0 : if (m.Group != DataHeatBalance::MaterialGroup::RegularMaterial || m.ROnly) {
11091 0 : ErrorsFound = true;
11092 0 : ShowSevereError(state,
11093 0 : cCurrentModuleObject + "=\"" + fndInput.name + "\", invalid " + state.dataIPShortCut->cAlphaFieldNames(alpF) +
11094 0 : "=\"" + state.dataIPShortCut->cAlphaArgs(alpF));
11095 0 : ShowContinueError(state, "Must be of type \"Material\"");
11096 0 : continue;
11097 : }
11098 0 : fndInput.footing.material = Kiva::Material(m.Conductivity, m.Density, m.SpecHeat);
11099 0 : fndInput.footing.width = m.Thickness;
11100 0 : fndInput.footing.x = 0.0;
11101 0 : fndInput.footing.z = 0.0;
11102 : }
11103 7 : alpF++;
11104 :
11105 7 : if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF - 1)) {
11106 0 : if (state.dataIPShortCut->lNumericFieldBlanks(numF)) {
11107 0 : ErrorsFound = true;
11108 0 : ShowSevereError(state,
11109 0 : cCurrentModuleObject + "=\"" + fndInput.name + "\", " + state.dataIPShortCut->cAlphaFieldNames(alpF - 1) +
11110 0 : " defined, but no " + state.dataIPShortCut->cNumericFieldNames(numF) + "provided");
11111 0 : continue;
11112 : } else {
11113 0 : fndInput.footing.depth = state.dataIPShortCut->rNumericArgs(numF);
11114 : }
11115 0 : numF++;
11116 : } else {
11117 7 : if (!state.dataIPShortCut->lNumericFieldBlanks(numF)) {
11118 0 : ShowWarningError(state,
11119 0 : cCurrentModuleObject + "=\"" + fndInput.name + "\", no " + state.dataIPShortCut->cAlphaFieldNames(alpF - 1) +
11120 : " defined");
11121 0 : ShowContinueError(state, state.dataIPShortCut->cNumericFieldNames(numF) + " will not be used.");
11122 : }
11123 7 : numF++;
11124 : }
11125 :
11126 : // General Blocks
11127 7 : int numRemainingFields = NumAlphas - (alpF - 1) + NumProps - (numF - 1);
11128 7 : if (numRemainingFields > 0) {
11129 0 : int numBlocks = numRemainingFields / 4;
11130 0 : if (mod(numRemainingFields, 4) != 0) {
11131 0 : ShowWarningError(state,
11132 0 : format("{}=\"{}\", number of Block fields not even multiple of 4. Will read in {}",
11133 : cCurrentModuleObject,
11134 : fndInput.name,
11135 0 : numBlocks));
11136 : }
11137 0 : for (int blockNum = 0; blockNum < numBlocks; blockNum++) {
11138 0 : Kiva::InputBlock block;
11139 0 : if (!state.dataIPShortCut->lAlphaFieldBlanks(alpF)) {
11140 0 : int index = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(alpF), state.dataMaterial->Material);
11141 0 : if (index == 0) {
11142 0 : ErrorsFound = true;
11143 0 : ShowSevereError(state,
11144 0 : "Did not find matching material for " + cCurrentModuleObject + "=\"" + fndInput.name + "\", " +
11145 0 : state.dataIPShortCut->cAlphaFieldNames(alpF) +
11146 0 : ", missing material = " + state.dataIPShortCut->cAlphaArgs(alpF));
11147 0 : continue;
11148 : }
11149 0 : auto &m = state.dataMaterial->Material(index);
11150 0 : if (m.Group != DataHeatBalance::MaterialGroup::RegularMaterial || m.ROnly) {
11151 0 : ErrorsFound = true;
11152 0 : ShowSevereError(state,
11153 0 : cCurrentModuleObject + "=\"" + fndInput.name + "\", invalid " +
11154 0 : state.dataIPShortCut->cAlphaFieldNames(alpF) + "=\"" + state.dataIPShortCut->cAlphaArgs(alpF));
11155 0 : ShowContinueError(state, "Must be of type \"Material\"");
11156 0 : continue;
11157 : }
11158 0 : block.material = Kiva::Material(m.Conductivity, m.Density, m.SpecHeat);
11159 0 : block.width = m.Thickness;
11160 : } else {
11161 0 : ErrorsFound = true;
11162 0 : ShowSevereError(state,
11163 0 : cCurrentModuleObject + "=\"" + fndInput.name + "\", " + state.dataIPShortCut->cAlphaFieldNames(alpF) +
11164 : " is required and not given.");
11165 0 : continue;
11166 : }
11167 0 : alpF++;
11168 :
11169 0 : if (state.dataIPShortCut->lNumericFieldBlanks(numF)) {
11170 0 : block.depth = 0.0; // Temporary indicator to default to foundation depth
11171 : } else {
11172 0 : block.depth = state.dataIPShortCut->rNumericArgs(numF);
11173 : }
11174 0 : numF++;
11175 :
11176 0 : if (state.dataIPShortCut->lNumericFieldBlanks(numF)) {
11177 0 : ErrorsFound = true;
11178 0 : ShowSevereError(state,
11179 0 : cCurrentModuleObject + "=\"" + fndInput.name + "\", " + state.dataIPShortCut->cAlphaFieldNames(alpF - 1) +
11180 0 : " defined, but no " + state.dataIPShortCut->cNumericFieldNames(numF) + "provided");
11181 0 : continue;
11182 : } else {
11183 0 : block.x = state.dataIPShortCut->rNumericArgs(numF);
11184 : }
11185 0 : numF++;
11186 :
11187 0 : if (state.dataIPShortCut->lNumericFieldBlanks(numF)) {
11188 0 : block.z = 0.0;
11189 : } else {
11190 0 : block.z = state.dataIPShortCut->rNumericArgs(numF);
11191 : }
11192 0 : numF++;
11193 :
11194 0 : fnd.inputBlocks.push_back(block);
11195 : }
11196 : }
11197 :
11198 7 : state.dataSurfaceGeometry->kivaManager.foundationInputs.push_back(fndInput);
11199 : }
11200 : }
11201 771 : }
11202 :
11203 771 : void GetOSCData(EnergyPlusData &state, bool &ErrorsFound)
11204 : {
11205 :
11206 : // SUBROUTINE INFORMATION:
11207 : // AUTHOR Linda Lawrie
11208 : // DATE WRITTEN May 2000
11209 : // MODIFIED Jul 2011, M.J. Witte and C.O. Pedersen, add new fields to OSC for last T, max and min
11210 : // RE-ENGINEERED na
11211 :
11212 : // PURPOSE OF THIS SUBROUTINE:
11213 : // This subroutine gets the OtherSideCoefficient data.
11214 :
11215 : // METHODOLOGY EMPLOYED:
11216 : // na
11217 :
11218 : // REFERENCES:
11219 : // Other Side Coefficient Definition
11220 : // OtherSideCoefficients,
11221 : // \memo This object sets the other side conditions for a surface in a variety of ways.
11222 : // A1, \field OtherSideCoeff Name
11223 : // \required-field
11224 : // \reference OSCNames
11225 : // \reference OutFaceEnvNames
11226 : // N1, \field Combined convective/radiative film coefficient
11227 : // \required-field
11228 : // \type real
11229 : // \note if>0, N1 becomes exterior convective/radiative film coefficient and other fields
11230 : // \note are used to calc outside air temp then exterior surface temp based on outside air
11231 : // \note and specified coefficient
11232 : // \note if<=0, then remaining fields calculate the outside surface temperature(?)
11233 : // \note following fields are used in the equation:
11234 : // \note SurfTemp=N7*TempZone + N4*OutsideDryBulb + N2*N3 + GroundTemp*N5 + WindSpeed*N6*OutsideDryBulb
11235 : // N2, \field User selected Constant Temperature
11236 : // \units C
11237 : // \type real
11238 : // \note This parameter will be overwritten by the values from the schedule(A2 below) if one is present
11239 : // N3, \field Coefficient modifying the user selected constant temperature
11240 : // \note This coefficient is used even with a schedule. It should normally be 1.0 in that case
11241 : // N4, \field Coefficient modifying the external dry bulb temperature
11242 : // \type real
11243 : // N5, \field Coefficient modifying the ground temperature
11244 : // \type real
11245 : // N6, \field Coefficient modifying the wind speed term (s/m)
11246 : // \type real
11247 : // N7, \field Coefficient modifying the zone air temperature part of the equation
11248 : // \type real
11249 : // A2, \field ScheduleName for constant temperature
11250 : // \note Name of Schedule for values of "const" temperature.
11251 : // \note Schedule values replace N2 - User selected constant temperature.
11252 : // \type object-list
11253 : // \object-list ScheduleNames
11254 : // A3, \field Sinusoidal Variation of Constant Temperature Coefficient
11255 : // \note Optionally used to vary Constant Temperature Coefficient with unitary sine wave
11256 : // \type choice
11257 : // \key Yes
11258 : // \key No
11259 : // \default No
11260 : // N8; \field Period of Sinusoidal Variation
11261 : // \note Use with sinusoidal variation to define the time period
11262 : // \type real
11263 : // \units hr
11264 : // \default 24
11265 : // N9, \field Previous Other Side Temperature Coefficient
11266 : // \note This coeffient multiplies the other side temperature result from the
11267 : // \note previous zone timestep
11268 : // \type real
11269 : // \default 0
11270 : // N10, \field Minimum Other Side Temperature
11271 : // \type real
11272 : // \units C
11273 : // \default -100
11274 : // N11; \field Maximum Other Side Temperature
11275 : // \type real
11276 : // \units C
11277 : // \default 200
11278 :
11279 : // Using/Aliasing
11280 :
11281 : using ScheduleManager::GetScheduleIndex;
11282 :
11283 : // Locals
11284 : // SUBROUTINE ARGUMENT DEFINITIONS:
11285 :
11286 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
11287 : int NumAlphas;
11288 : int NumProps;
11289 : int Loop;
11290 : int IOStat;
11291 : int OSCNum;
11292 : bool ErrorInName;
11293 : bool IsBlank;
11294 1542 : std::string cOSCLimitsString;
11295 771 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
11296 :
11297 771 : cCurrentModuleObject = "SurfaceProperty:OtherSideCoefficients";
11298 771 : state.dataSurface->TotOSC = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
11299 771 : state.dataSurface->OSC.allocate(state.dataSurface->TotOSC);
11300 :
11301 771 : OSCNum = 0;
11302 789 : for (Loop = 1; Loop <= state.dataSurface->TotOSC; ++Loop) {
11303 126 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
11304 : cCurrentModuleObject,
11305 : Loop,
11306 18 : state.dataIPShortCut->cAlphaArgs,
11307 : NumAlphas,
11308 18 : state.dataIPShortCut->rNumericArgs,
11309 : NumProps,
11310 : IOStat,
11311 18 : state.dataIPShortCut->lNumericFieldBlanks,
11312 18 : state.dataIPShortCut->lAlphaFieldBlanks,
11313 18 : state.dataIPShortCut->cAlphaFieldNames,
11314 18 : state.dataIPShortCut->cNumericFieldNames);
11315 18 : ErrorInName = false;
11316 18 : IsBlank = false;
11317 36 : UtilityRoutines::VerifyName(
11318 54 : state, state.dataIPShortCut->cAlphaArgs(1), state.dataSurface->OSC, OSCNum, ErrorInName, IsBlank, cCurrentModuleObject + " Name");
11319 18 : if (ErrorInName) {
11320 0 : ErrorsFound = true;
11321 0 : continue;
11322 : }
11323 :
11324 18 : ++OSCNum;
11325 18 : state.dataSurface->OSC(OSCNum).Name = state.dataIPShortCut->cAlphaArgs(1);
11326 18 : state.dataSurface->OSC(OSCNum).SurfFilmCoef = state.dataIPShortCut->rNumericArgs(1);
11327 18 : state.dataSurface->OSC(OSCNum).ConstTemp = state.dataIPShortCut->rNumericArgs(2); // This will be replaced if schedule is used
11328 18 : state.dataSurface->OSC(OSCNum).ConstTempCoef =
11329 18 : state.dataIPShortCut->rNumericArgs(3); // This multiplier is used (even with schedule). It should normally be 1.0
11330 18 : state.dataSurface->OSC(OSCNum).ExtDryBulbCoef = state.dataIPShortCut->rNumericArgs(4);
11331 18 : state.dataSurface->OSC(OSCNum).GroundTempCoef = state.dataIPShortCut->rNumericArgs(5);
11332 18 : state.dataSurface->OSC(OSCNum).WindSpeedCoef = state.dataIPShortCut->rNumericArgs(6);
11333 18 : state.dataSurface->OSC(OSCNum).ZoneAirTempCoef = state.dataIPShortCut->rNumericArgs(7);
11334 18 : state.dataSurface->OSC(OSCNum).SinusoidPeriod = state.dataIPShortCut->rNumericArgs(8);
11335 :
11336 18 : if ((!state.dataIPShortCut->lAlphaFieldBlanks(2)) && (NumAlphas != 1)) { // Const temp will come from schedule specified below.
11337 15 : state.dataSurface->OSC(OSCNum).ConstTempScheduleName = state.dataIPShortCut->cAlphaArgs(2);
11338 15 : if (!state.dataSurface->OSC(OSCNum).ConstTempScheduleName.empty()) {
11339 15 : state.dataSurface->OSC(OSCNum).ConstTempScheduleIndex =
11340 15 : GetScheduleIndex(state, state.dataSurface->OSC(OSCNum).ConstTempScheduleName);
11341 15 : if (state.dataSurface->OSC(OSCNum).ConstTempScheduleIndex == 0) {
11342 0 : ShowSevereError(state,
11343 0 : cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", invalid " +
11344 0 : state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2));
11345 0 : ErrorsFound = true;
11346 : }
11347 : }
11348 : }
11349 :
11350 18 : if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) {
11351 :
11352 15 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "No")) {
11353 14 : state.dataSurface->OSC(OSCNum).SinusoidalConstTempCoef = false;
11354 1 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "Yes")) {
11355 1 : state.dataSurface->OSC(OSCNum).SinusoidalConstTempCoef = true;
11356 : } else {
11357 0 : ShowSevereError(state,
11358 0 : cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", invalid " +
11359 0 : state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3));
11360 0 : ErrorsFound = true;
11361 : }
11362 : }
11363 :
11364 18 : if (state.dataIPShortCut->rNumericArgs(1) > 0.0 && !any_ne(state.dataIPShortCut->rNumericArgs({3, 7}), 0.0) &&
11365 0 : (!state.dataSurface->OSC(OSCNum).SinusoidalConstTempCoef)) {
11366 0 : ShowSevereError(state, cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" has zeros for all coefficients.");
11367 0 : ShowContinueError(state, "...The outdoor air temperature for surfaces using this OtherSideCoefficients object will always be 0C.");
11368 : }
11369 :
11370 19 : if (state.dataIPShortCut->rNumericArgs(1) <= 0.0 && !any_ne(state.dataIPShortCut->rNumericArgs({3, 7}), 0.0) &&
11371 1 : (!state.dataSurface->OSC(OSCNum).SinusoidalConstTempCoef)) {
11372 0 : ShowSevereError(state, cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" has zeros for all coefficients.");
11373 0 : ShowContinueError(state,
11374 : "...The outside surface temperature for surfaces using this OtherSideCoefficients object will always be 0C.");
11375 : }
11376 :
11377 18 : state.dataSurface->OSC(OSCNum).TPreviousCoef = state.dataIPShortCut->rNumericArgs(9);
11378 :
11379 18 : if (!state.dataIPShortCut->lNumericFieldBlanks(10)) {
11380 1 : state.dataSurface->OSC(OSCNum).MinLimitPresent = true;
11381 1 : state.dataSurface->OSC(OSCNum).MinTempLimit = state.dataIPShortCut->rNumericArgs(10);
11382 1 : cOSCLimitsString = format("{:.3R}", state.dataIPShortCut->rNumericArgs(10));
11383 : } else {
11384 17 : cOSCLimitsString = "N/A";
11385 : }
11386 18 : if (!state.dataIPShortCut->lNumericFieldBlanks(11)) {
11387 1 : state.dataSurface->OSC(OSCNum).MaxLimitPresent = true;
11388 1 : state.dataSurface->OSC(OSCNum).MaxTempLimit = state.dataIPShortCut->rNumericArgs(11);
11389 1 : cOSCLimitsString += format(",{:.3R}", state.dataIPShortCut->rNumericArgs(10));
11390 : } else {
11391 17 : cOSCLimitsString += ",N/A";
11392 : }
11393 : }
11394 :
11395 789 : for (Loop = 1; Loop <= state.dataSurface->TotOSC; ++Loop) {
11396 18 : if (Loop == 1) {
11397 : static constexpr std::string_view OSCFormat1(
11398 : "! <Other Side Coefficients>,Name,Combined convective/radiative film coefficient {W/m2-K},User selected "
11399 : "Constant Temperature {C},Coefficient modifying the constant temperature term,Coefficient modifying the external "
11400 : "dry bulb temperature term,Coefficient modifying the ground temperature term,Coefficient modifying the wind speed "
11401 : "term {s/m},Coefficient modifying the zone air temperature term,Constant Temperature Schedule Name,Sinusoidal "
11402 : "Variation,Period of Sinusoidal Variation,Previous Other Side Temperature Coefficient,Minimum Other Side "
11403 : "Temperature {C},Maximum Other Side Temperature {C}");
11404 8 : print(state.files.eio, "{}\n", OSCFormat1);
11405 : }
11406 18 : if (state.dataSurface->OSC(Loop).SurfFilmCoef > 0.0) {
11407 1 : state.dataIPShortCut->cAlphaArgs(1) = format("{:.3R}", state.dataSurface->OSC(Loop).SurfFilmCoef);
11408 4 : SetupOutputVariable(state,
11409 : "Surface Other Side Coefficients Exterior Air Drybulb Temperature",
11410 : OutputProcessor::Unit::C,
11411 1 : state.dataSurface->OSC(Loop).OSCTempCalc,
11412 : OutputProcessor::SOVTimeStepType::System,
11413 : OutputProcessor::SOVStoreType::Average,
11414 2 : state.dataSurface->OSC(Loop).Name);
11415 : } else {
11416 17 : state.dataIPShortCut->cAlphaArgs(1) = "N/A";
11417 : }
11418 18 : if (state.dataSurface->OSC(Loop).ConstTempScheduleIndex != 0) {
11419 15 : state.dataIPShortCut->cAlphaArgs(2) = state.dataSurface->OSC(Loop).ConstTempScheduleName;
11420 15 : constexpr auto format{"Other Side Coefficients,{},{},{},{:.3R},{:.3R},{:.3R},{:.3R},{:.3R},{},{},{:.3R},{:.3R},{}\n"};
11421 180 : print(state.files.eio,
11422 : format,
11423 15 : state.dataSurface->OSC(Loop).Name,
11424 15 : state.dataIPShortCut->cAlphaArgs(1),
11425 : "N/A",
11426 15 : state.dataSurface->OSC(Loop).ConstTempCoef,
11427 15 : state.dataSurface->OSC(Loop).ExtDryBulbCoef,
11428 15 : state.dataSurface->OSC(Loop).GroundTempCoef,
11429 15 : state.dataSurface->OSC(Loop).WindSpeedCoef,
11430 15 : state.dataSurface->OSC(Loop).ZoneAirTempCoef,
11431 15 : state.dataIPShortCut->cAlphaArgs(2),
11432 15 : state.dataIPShortCut->cAlphaArgs(3),
11433 15 : state.dataSurface->OSC(Loop).SinusoidPeriod,
11434 15 : state.dataSurface->OSC(Loop).TPreviousCoef,
11435 15 : cOSCLimitsString);
11436 : } else {
11437 3 : state.dataIPShortCut->cAlphaArgs(2) = "N/A";
11438 3 : constexpr auto format{"Other Side Coefficients,{},{},{:.2R},{:.3R},{:.3R},{:.3R},{:.3R},{:.3R},{},{},{:.3R},{:.3R},{}\n"};
11439 39 : print(state.files.eio,
11440 : format,
11441 3 : state.dataSurface->OSC(Loop).Name,
11442 3 : state.dataIPShortCut->cAlphaArgs(1),
11443 3 : state.dataSurface->OSC(Loop).ConstTemp,
11444 3 : state.dataSurface->OSC(Loop).ConstTempCoef,
11445 3 : state.dataSurface->OSC(Loop).ExtDryBulbCoef,
11446 3 : state.dataSurface->OSC(Loop).GroundTempCoef,
11447 3 : state.dataSurface->OSC(Loop).WindSpeedCoef,
11448 3 : state.dataSurface->OSC(Loop).ZoneAirTempCoef,
11449 3 : state.dataIPShortCut->cAlphaArgs(2),
11450 3 : state.dataIPShortCut->cAlphaArgs(3),
11451 3 : state.dataSurface->OSC(Loop).SinusoidPeriod,
11452 3 : state.dataSurface->OSC(Loop).TPreviousCoef,
11453 3 : cOSCLimitsString);
11454 : }
11455 : }
11456 771 : }
11457 :
11458 771 : void GetOSCMData(EnergyPlusData &state, bool &ErrorsFound)
11459 : {
11460 :
11461 : // SUBROUTINE INFORMATION:
11462 : // AUTHOR Brent Griffith
11463 : // DATE WRITTEN November 2004
11464 : // MODIFIED na
11465 : // RE-ENGINEERED na
11466 :
11467 : // PURPOSE OF THIS SUBROUTINE:
11468 : // This subroutine gets the OtherSideConditionsModel data.
11469 :
11470 : // METHODOLOGY EMPLOYED:
11471 : // na
11472 :
11473 : // REFERENCES:
11474 : // derived from GetOSCData subroutine by Linda Lawrie
11475 :
11476 : // OtherSideConditionsModel,
11477 : // \memo This object sets up modifying the other side conditions for a surface from other model results.
11478 : // A1, \field OtherSideConditionsModel Name
11479 : // \required-field
11480 : // \reference OSCMNames
11481 : // \reference OutFaceEnvNames
11482 : // A2; \field Type of Model to determine Boundary Conditions
11483 : // \type choice
11484 : // \key Transpired Collector
11485 : // \key Vented PV Cavity
11486 : // \key Hybrid PV Transpired Collector
11487 :
11488 : // Using/Aliasing
11489 :
11490 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
11491 : int NumAlphas;
11492 : int NumProps;
11493 : int Loop;
11494 : int IOStat;
11495 : int OSCMNum;
11496 : bool ErrorInName;
11497 : bool IsBlank;
11498 771 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
11499 771 : cCurrentModuleObject = "SurfaceProperty:OtherSideConditionsModel";
11500 771 : state.dataSurface->TotOSCM = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
11501 771 : state.dataSurface->OSCM.allocate(state.dataSurface->TotOSCM);
11502 : // OSCM is already initialized in derived type defn.
11503 :
11504 771 : OSCMNum = 0;
11505 791 : for (Loop = 1; Loop <= state.dataSurface->TotOSCM; ++Loop) {
11506 60 : state.dataInputProcessing->inputProcessor->getObjectItem(
11507 40 : state, cCurrentModuleObject, Loop, state.dataIPShortCut->cAlphaArgs, NumAlphas, state.dataIPShortCut->rNumericArgs, NumProps, IOStat);
11508 20 : ErrorInName = false;
11509 20 : IsBlank = false;
11510 40 : UtilityRoutines::VerifyName(
11511 60 : state, state.dataIPShortCut->cAlphaArgs(1), state.dataSurface->OSCM, OSCMNum, ErrorInName, IsBlank, cCurrentModuleObject + " Name");
11512 20 : if (ErrorInName) {
11513 0 : ErrorsFound = true;
11514 0 : continue;
11515 : }
11516 :
11517 20 : ++OSCMNum;
11518 20 : state.dataSurface->OSCM(OSCMNum).Name = state.dataIPShortCut->cAlphaArgs(1);
11519 : // Note no validation of the below at this time:
11520 20 : state.dataSurface->OSCM(OSCMNum).Class = state.dataIPShortCut->cAlphaArgs(2);
11521 : // setup output vars for modeled coefficients
11522 80 : SetupOutputVariable(state,
11523 : "Surface Other Side Conditions Modeled Convection Air Temperature",
11524 : OutputProcessor::Unit::C,
11525 20 : state.dataSurface->OSCM(OSCMNum).TConv,
11526 : OutputProcessor::SOVTimeStepType::System,
11527 : OutputProcessor::SOVStoreType::Average,
11528 40 : state.dataSurface->OSCM(OSCMNum).Name);
11529 80 : SetupOutputVariable(state,
11530 : "Surface Other Side Conditions Modeled Convection Heat Transfer Coefficient",
11531 : OutputProcessor::Unit::W_m2K,
11532 20 : state.dataSurface->OSCM(OSCMNum).HConv,
11533 : OutputProcessor::SOVTimeStepType::System,
11534 : OutputProcessor::SOVStoreType::Average,
11535 40 : state.dataSurface->OSCM(OSCMNum).Name);
11536 80 : SetupOutputVariable(state,
11537 : "Surface Other Side Conditions Modeled Radiation Temperature",
11538 : OutputProcessor::Unit::C,
11539 20 : state.dataSurface->OSCM(OSCMNum).TRad,
11540 : OutputProcessor::SOVTimeStepType::System,
11541 : OutputProcessor::SOVStoreType::Average,
11542 40 : state.dataSurface->OSCM(OSCMNum).Name);
11543 80 : SetupOutputVariable(state,
11544 : "Surface Other Side Conditions Modeled Radiation Heat Transfer Coefficient",
11545 : OutputProcessor::Unit::W_m2K,
11546 20 : state.dataSurface->OSCM(OSCMNum).HRad,
11547 : OutputProcessor::SOVTimeStepType::System,
11548 : OutputProcessor::SOVStoreType::Average,
11549 40 : state.dataSurface->OSCM(OSCMNum).Name);
11550 :
11551 20 : if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
11552 0 : SetupEMSActuator(state,
11553 : "Other Side Boundary Conditions",
11554 0 : state.dataSurface->OSCM(OSCMNum).Name,
11555 : "Convection Bulk Air Temperature",
11556 : "[C]",
11557 0 : state.dataSurface->OSCM(OSCMNum).EMSOverrideOnTConv,
11558 0 : state.dataSurface->OSCM(OSCMNum).EMSOverrideTConvValue);
11559 0 : SetupEMSActuator(state,
11560 : "Other Side Boundary Conditions",
11561 0 : state.dataSurface->OSCM(OSCMNum).Name,
11562 : "Convection Heat Transfer Coefficient",
11563 : "[W/m2-K]",
11564 0 : state.dataSurface->OSCM(OSCMNum).EMSOverrideOnHConv,
11565 0 : state.dataSurface->OSCM(OSCMNum).EMSOverrideHConvValue);
11566 0 : SetupEMSActuator(state,
11567 : "Other Side Boundary Conditions",
11568 0 : state.dataSurface->OSCM(OSCMNum).Name,
11569 : "Radiation Effective Temperature",
11570 : "[C]",
11571 0 : state.dataSurface->OSCM(OSCMNum).EMSOverrideOnTRad,
11572 0 : state.dataSurface->OSCM(OSCMNum).EMSOverrideTRadValue);
11573 0 : SetupEMSActuator(state,
11574 : "Other Side Boundary Conditions",
11575 0 : state.dataSurface->OSCM(OSCMNum).Name,
11576 : "Radiation Linear Heat Transfer Coefficient",
11577 : "[W/m2-K]",
11578 0 : state.dataSurface->OSCM(OSCMNum).EMSOverrideOnHrad,
11579 0 : state.dataSurface->OSCM(OSCMNum).EMSOverrideHradValue);
11580 : }
11581 : }
11582 :
11583 791 : for (Loop = 1; Loop <= state.dataSurface->TotOSCM; ++Loop) {
11584 20 : if (Loop == 1) {
11585 : static constexpr std::string_view OSCMFormat1("! <Other Side Conditions Model>,Name,Class\n");
11586 11 : print(state.files.eio, OSCMFormat1);
11587 : }
11588 20 : print(state.files.eio, "Other Side Conditions Model,{},{}\n", state.dataSurface->OSCM(Loop).Name, state.dataSurface->OSCM(Loop).Class);
11589 : }
11590 771 : }
11591 :
11592 771 : void GetMovableInsulationData(EnergyPlusData &state, bool &ErrorsFound) // If errors found in input
11593 : {
11594 :
11595 : // SUBROUTINE INFORMATION:
11596 : // AUTHOR Linda Lawrie
11597 : // DATE WRITTEN May 2000
11598 : // MODIFIED na
11599 : // RE-ENGINEERED na
11600 :
11601 : // PURPOSE OF THIS SUBROUTINE:
11602 : // This subroutine gets the movable insulation data that can be associated with
11603 : // a surface.
11604 :
11605 : // METHODOLOGY EMPLOYED:
11606 : // na
11607 :
11608 : // REFERENCES:
11609 : // Movable Insulation Definition
11610 : // SurfaceControl:MovableInsulation,
11611 : // \memo Exterior or Interior Insulation on opaque surfaces
11612 : // A1, \field Insulation Type
11613 : // \required-field
11614 : // \type choice
11615 : // \key Outside
11616 : // \key Inside
11617 : // A2, \field Surface Name
11618 : // \required-field
11619 : // \type object-list
11620 : // \object-list SurfaceNames
11621 : // A3, \field Material Name
11622 : // \required-field
11623 : // \object-list MaterialName
11624 : // A4; \field Schedule Name
11625 : // \required-field
11626 : // \type object-list
11627 : // \object-list ScheduleNames
11628 :
11629 : // Using/Aliasing
11630 :
11631 : using ScheduleManager::GetScheduleIndex;
11632 :
11633 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
11634 : int NAlphas;
11635 : int NNums;
11636 : int IOStat;
11637 : int Loop;
11638 : int NMatInsul;
11639 : int SurfNum;
11640 : int MaterNum;
11641 : int SchNum;
11642 :
11643 : enum class InsulationType
11644 : {
11645 : Invalid = -1,
11646 : Outside,
11647 : Inside,
11648 : Num
11649 : };
11650 771 : constexpr std::array<std::string_view, static_cast<int>(InsulationType::Num)> insulationTypeNamesUC = {"OUTSIDE", "INSIDE"};
11651 :
11652 771 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
11653 771 : cCurrentModuleObject = "SurfaceControl:MovableInsulation";
11654 771 : NMatInsul = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
11655 776 : for (Loop = 1; Loop <= NMatInsul; ++Loop) {
11656 35 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
11657 : cCurrentModuleObject,
11658 : Loop,
11659 5 : state.dataIPShortCut->cAlphaArgs,
11660 : NAlphas,
11661 5 : state.dataIPShortCut->rNumericArgs,
11662 : NNums,
11663 : IOStat,
11664 5 : state.dataIPShortCut->lNumericFieldBlanks,
11665 5 : state.dataIPShortCut->lAlphaFieldBlanks,
11666 5 : state.dataIPShortCut->cAlphaFieldNames,
11667 5 : state.dataIPShortCut->cNumericFieldNames);
11668 5 : SurfNum =
11669 5 : UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(2), state.dataSurface->Surface, state.dataSurface->TotSurfaces);
11670 5 : MaterNum =
11671 5 : UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(3), state.dataMaterial->Material, state.dataHeatBal->TotMaterials);
11672 5 : SchNum = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(4));
11673 : InsulationType insulationType =
11674 5 : static_cast<InsulationType>(getEnumerationValue(insulationTypeNamesUC, state.dataIPShortCut->cAlphaArgs(1)));
11675 5 : if (insulationType == InsulationType::Invalid) {
11676 0 : ShowSevereError(state,
11677 0 : cCurrentModuleObject + ", " + state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" +
11678 0 : state.dataIPShortCut->cAlphaArgs(2) + "\", invalid data.");
11679 0 : ShowContinueError(state,
11680 0 : " invalid " + state.dataIPShortCut->cAlphaFieldNames(1) + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
11681 : "\", [should be Inside or Outside]");
11682 0 : ErrorsFound = true;
11683 : }
11684 5 : if (SurfNum == 0) {
11685 0 : ShowSevereError(state,
11686 0 : cCurrentModuleObject + ", " + state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" +
11687 0 : state.dataIPShortCut->cAlphaArgs(2) + "\", invalid data.");
11688 0 : ShowContinueError(state, " invalid (not found) " + state.dataIPShortCut->cAlphaFieldNames(2));
11689 0 : ErrorsFound = true;
11690 : } else {
11691 5 : if (MaterNum == 0) {
11692 0 : ShowSevereError(state,
11693 0 : cCurrentModuleObject + ", " + state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" +
11694 0 : state.dataIPShortCut->cAlphaArgs(2) + "\", invalid data.");
11695 0 : ShowContinueError(state,
11696 0 : " invalid (not found) " + state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" +
11697 0 : state.dataIPShortCut->cAlphaArgs(3) + "\"");
11698 0 : ErrorsFound = true;
11699 : } else {
11700 :
11701 : Array1D_string const cMaterialGroupType({-1, 18},
11702 : {"invalid",
11703 : "Material/Material:NoMass",
11704 : "Material:AirGap",
11705 : "WindowMaterial:Shade",
11706 : "WindowMaterial:Glazing*",
11707 : "WindowMaterial:Gas",
11708 : "WindowMaterial:Blind",
11709 : "WindowMaterial:GasMixture",
11710 : "WindowMaterial:Screen",
11711 : "Material:RoofVegetation",
11712 : "Material:InfraredTransparent",
11713 : "WindowMaterial:SimpleGlazingSystem",
11714 : "WindowMaterial:ComplexShade",
11715 : "WindowMaterial:Gap",
11716 : "WindowMaterial:Glazing:EquivalentLayer",
11717 : "WindowMaterial:Shade:EquivalentLayer",
11718 : "WindowMaterial:Drape:EquivalentLayer",
11719 : "WindowMaterial:Blind:EquivalentLayer",
11720 : "WindowMaterial:Screen:EquivalentLayer",
11721 10 : "WindowMaterial:Gap:EquivalentLayer"});
11722 :
11723 5 : DataHeatBalance::MaterialGroup const MaterialLayerGroup = state.dataMaterial->Material(MaterNum).Group;
11724 5 : if (BITF_TEST_ANY(BITF(MaterialLayerGroup),
11725 : BITF(DataHeatBalance::MaterialGroup::WindowSimpleGlazing) |
11726 : BITF(DataHeatBalance::MaterialGroup::ShadeEquivalentLayer) |
11727 : BITF(DataHeatBalance::MaterialGroup::DrapeEquivalentLayer) |
11728 : BITF(DataHeatBalance::MaterialGroup::BlindEquivalentLayer) |
11729 : BITF(DataHeatBalance::MaterialGroup::ScreenEquivalentLayer) |
11730 : BITF(DataHeatBalance::MaterialGroup::GapEquivalentLayer))) {
11731 0 : ShowSevereError(state, "Invalid movable insulation material for " + cCurrentModuleObject + ":");
11732 0 : ShowSevereError(
11733 0 : state, "...Movable insulation material type specified = " + cMaterialGroupType(static_cast<int>(MaterialLayerGroup)));
11734 0 : ShowSevereError(state, "...Movable insulation material name specified = " + state.dataIPShortCut->cAlphaArgs(3));
11735 0 : ErrorsFound = true;
11736 : }
11737 5 : if (SchNum == 0) {
11738 0 : ShowSevereError(state,
11739 0 : cCurrentModuleObject + ", " + state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" +
11740 0 : state.dataIPShortCut->cAlphaArgs(2) + "\", invalid data.");
11741 0 : ShowContinueError(state,
11742 0 : " invalid (not found) " + state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" +
11743 0 : state.dataIPShortCut->cAlphaArgs(4) + "\"");
11744 0 : ErrorsFound = true;
11745 : } else {
11746 : {
11747 5 : switch (insulationType) {
11748 2 : case InsulationType::Outside:
11749 2 : if (state.dataSurface->SurfMaterialMovInsulExt(SurfNum) > 0) {
11750 0 : ShowSevereError(state,
11751 0 : cCurrentModuleObject + ", " + state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" +
11752 0 : state.dataIPShortCut->cAlphaArgs(2) + "\", already assigned.");
11753 0 : ShowContinueError(state,
11754 0 : "\"Outside\", was already assigned Material=\"" +
11755 0 : state.dataMaterial->Material(state.dataSurface->SurfMaterialMovInsulInt(SurfNum)).Name +
11756 : "\".");
11757 0 : ShowContinueError(state,
11758 0 : "attempting to assign Material=\"" + state.dataMaterial->Material(MaterNum).Name + "\".");
11759 0 : ErrorsFound = true;
11760 : }
11761 2 : state.dataSurface->SurfMaterialMovInsulExt(SurfNum) = MaterNum;
11762 2 : state.dataSurface->SurfSchedMovInsulExt(SurfNum) = SchNum;
11763 2 : state.dataSurface->AnyMovableInsulation = true;
11764 2 : if (state.dataMaterial->Material(MaterNum).Resistance <= 0.0) {
11765 0 : if (state.dataMaterial->Material(MaterNum).Conductivity <= 0.0 ||
11766 0 : state.dataMaterial->Material(MaterNum).Thickness <= 0.0) {
11767 0 : ShowSevereError(state,
11768 0 : cCurrentModuleObject + ", " + state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" +
11769 0 : state.dataIPShortCut->cAlphaArgs(2) + "\", invalid material.");
11770 0 : ShowContinueError(state, "\"Outside\", invalid material for movable insulation.");
11771 0 : ShowContinueError(state,
11772 0 : format("Material=\"{}\",Resistance=[{:.3R}], must be > 0 for use in Movable Insulation.",
11773 0 : state.dataMaterial->Material(MaterNum).Name,
11774 0 : state.dataMaterial->Material(MaterNum).Resistance));
11775 0 : ErrorsFound = true;
11776 0 : } else if (state.dataMaterial->Material(MaterNum).Conductivity > 0.0) {
11777 0 : state.dataMaterial->Material(MaterNum).Resistance =
11778 0 : state.dataMaterial->Material(MaterNum).Thickness / state.dataMaterial->Material(MaterNum).Conductivity;
11779 : }
11780 : }
11781 2 : if (state.dataMaterial->Material(MaterNum).Conductivity <= 0.0) {
11782 1 : if (state.dataMaterial->Material(MaterNum).Resistance <= 0.0) {
11783 0 : ShowSevereError(state,
11784 0 : cCurrentModuleObject + ", " + state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" +
11785 0 : state.dataIPShortCut->cAlphaArgs(2) + "\", invalid material.");
11786 0 : ShowContinueError(state, "\"Outside\", invalid material for movable insulation.");
11787 0 : ShowContinueError(state,
11788 0 : format("Material=\"{}\",Conductivity=[{:.3R}], must be > 0 for use in Movable Insulation.",
11789 0 : state.dataMaterial->Material(MaterNum).Name,
11790 0 : state.dataMaterial->Material(MaterNum).Conductivity));
11791 0 : ErrorsFound = true;
11792 : }
11793 : }
11794 2 : break;
11795 3 : case InsulationType::Inside:
11796 3 : if (state.dataSurface->SurfMaterialMovInsulInt(SurfNum) > 0) {
11797 0 : ShowSevereError(state,
11798 0 : cCurrentModuleObject + ", " + state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" +
11799 0 : state.dataIPShortCut->cAlphaArgs(2) + "\", already assigned.");
11800 0 : ShowContinueError(state,
11801 0 : "\"Inside\", was already assigned Material=\"" +
11802 0 : state.dataMaterial->Material(state.dataSurface->SurfMaterialMovInsulInt(SurfNum)).Name +
11803 : "\".");
11804 0 : ShowContinueError(state,
11805 0 : "attempting to assign Material=\"" + state.dataMaterial->Material(MaterNum).Name + "\".");
11806 0 : ErrorsFound = true;
11807 : }
11808 3 : state.dataSurface->SurfMaterialMovInsulInt(SurfNum) = MaterNum;
11809 3 : state.dataSurface->SurfSchedMovInsulInt(SurfNum) = SchNum;
11810 3 : state.dataSurface->AnyMovableInsulation = true;
11811 3 : if (state.dataMaterial->Material(MaterNum).Resistance <= 0.0) {
11812 0 : if (state.dataMaterial->Material(MaterNum).Conductivity <= 0.0 ||
11813 0 : state.dataMaterial->Material(MaterNum).Thickness <= 0.0) {
11814 0 : ShowSevereError(state,
11815 0 : cCurrentModuleObject + ", " + state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" +
11816 0 : state.dataIPShortCut->cAlphaArgs(2) + "\", invalid material.");
11817 0 : ShowContinueError(state, "\"Inside\", invalid material for movable insulation.");
11818 0 : ShowContinueError(state,
11819 0 : format("Material=\"{}\",Resistance=[{:.3R}], must be > 0 for use in Movable Insulation.",
11820 0 : state.dataMaterial->Material(MaterNum).Name,
11821 0 : state.dataMaterial->Material(MaterNum).Resistance));
11822 0 : ErrorsFound = true;
11823 0 : } else if (state.dataMaterial->Material(MaterNum).Conductivity > 0.0) {
11824 0 : state.dataMaterial->Material(MaterNum).Resistance =
11825 0 : state.dataMaterial->Material(MaterNum).Thickness / state.dataMaterial->Material(MaterNum).Conductivity;
11826 : }
11827 : }
11828 3 : break;
11829 0 : default:
11830 0 : assert(false);
11831 : }
11832 : }
11833 5 : if (state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Window) {
11834 0 : ShowSevereError(state,
11835 0 : cCurrentModuleObject + ", " + state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" +
11836 0 : state.dataIPShortCut->cAlphaArgs(2) + "\"");
11837 0 : ShowContinueError(state, "invalid use on a Window. Use WindowShadingControl instead.");
11838 0 : ErrorsFound = true;
11839 : }
11840 : }
11841 : }
11842 : }
11843 : }
11844 771 : }
11845 :
11846 : // Calculates the volume (m3) of a zone using the surfaces as possible.
11847 771 : void CalculateZoneVolume(EnergyPlusData &state, const Array1D_bool &CeilingHeightEntered)
11848 : {
11849 :
11850 : // SUBROUTINE INFORMATION:
11851 : // AUTHOR Legacy Code
11852 : // DATE WRITTEN 1992-1994
11853 : // MODIFIED Sep 2007, Mar 2017
11854 :
11855 : // METHODOLOGY EMPLOYED:
11856 : // Uses surface area information for calculations. Modified to use the
11857 : // user-entered ceiling height (x floor area, if applicable) instead of using
11858 : // the calculated volume when the user enters the ceiling height.
11859 :
11860 : // REFERENCES:
11861 : // Legacy Code (IBLAST)
11862 :
11863 : using namespace Vectors;
11864 :
11865 : Real64 SumAreas; // Sum of the Zone surface areas that are not "internal mass"
11866 : Real64 SurfCount; // Surface Count
11867 : int SurfNum; // Loop counter for surfaces
11868 : int ZoneNum; // Loop counter for Zones
11869 1542 : Array1D_int surfacenotused;
11870 : int notused;
11871 : int NFaces;
11872 : int NActFaces;
11873 : Real64 CalcVolume;
11874 : bool initmsg;
11875 : int iside;
11876 771 : auto &ShowZoneSurfaceHeaders = state.dataSurfaceGeometry->ShowZoneSurfaceHeaders;
11877 771 : auto &ErrCount5 = state.dataSurfaceGeometry->ErrCount5;
11878 :
11879 : // Object Data
11880 1542 : Polyhedron ZoneStruct;
11881 :
11882 771 : initmsg = true;
11883 771 : bool ShowZoneSurfaces = (state.dataInputProcessing->inputProcessor->getNumSectionsFound("SHOWZONESURFACES_DEBUG") > 0);
11884 :
11885 : enum class ZoneVolumeCalcMethod
11886 : {
11887 : Invalid = -1,
11888 : Enclosed,
11889 : FloorAreaTimesHeight1,
11890 : FloorAreaTimesHeight2,
11891 : CeilingAreaTimesHeight,
11892 : OpWallAreaTimesDistance,
11893 : UserProvided,
11894 : Num
11895 : };
11896 :
11897 771 : int countNotFullyEnclosedZones = 0;
11898 5585 : for (ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
11899 4814 : auto &thisZone = state.dataHeatBal->Zone(ZoneNum);
11900 4814 : if (!state.dataHeatBal->Zone(ZoneNum).HasFloor) {
11901 6 : ShowWarningError(state,
11902 4 : "No floor exists in Zone=\"" + state.dataHeatBal->Zone(ZoneNum).Name +
11903 : "\", zone floor area is zero. All values for this zone that are entered per floor area will be zero.");
11904 : }
11905 :
11906 4814 : SumAreas = 0.0;
11907 4814 : SurfCount = 0.0;
11908 : // Use AllSurfaceFirst which includes air boundaries
11909 4814 : NFaces = state.dataHeatBal->Zone(ZoneNum).AllSurfaceLast - state.dataHeatBal->Zone(ZoneNum).AllSurfaceFirst + 1;
11910 4814 : notused = 0;
11911 4814 : ZoneStruct.NumSurfaceFaces = NFaces;
11912 4814 : ZoneStruct.SurfaceFace.allocate(NFaces);
11913 4814 : NActFaces = 0;
11914 4814 : surfacenotused.dimension(NFaces, 0);
11915 :
11916 47034 : for (SurfNum = state.dataHeatBal->Zone(ZoneNum).AllSurfaceFirst; SurfNum <= state.dataHeatBal->Zone(ZoneNum).AllSurfaceLast; ++SurfNum) {
11917 :
11918 : // Only include Base Surfaces in Calc.
11919 :
11920 113904 : if (state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Wall &&
11921 56436 : state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Floor &&
11922 14216 : state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Roof) {
11923 8726 : ++notused;
11924 8726 : surfacenotused(notused) = SurfNum;
11925 8726 : continue;
11926 : }
11927 :
11928 33494 : ++NActFaces;
11929 33494 : ZoneStruct.SurfaceFace(NActFaces).FacePoints.allocate(state.dataSurface->Surface(SurfNum).Sides);
11930 33494 : ZoneStruct.SurfaceFace(NActFaces).NSides = state.dataSurface->Surface(SurfNum).Sides;
11931 33494 : ZoneStruct.SurfaceFace(NActFaces).SurfNum = SurfNum;
11932 33494 : ZoneStruct.SurfaceFace(NActFaces).FacePoints({1, state.dataSurface->Surface(SurfNum).Sides}) =
11933 66988 : state.dataSurface->Surface(SurfNum).Vertex({1, state.dataSurface->Surface(SurfNum).Sides});
11934 66988 : CreateNewellAreaVector(ZoneStruct.SurfaceFace(NActFaces).FacePoints,
11935 33494 : ZoneStruct.SurfaceFace(NActFaces).NSides,
11936 33494 : ZoneStruct.SurfaceFace(NActFaces).NewellAreaVector);
11937 33494 : SumAreas += VecLength(ZoneStruct.SurfaceFace(NActFaces).NewellAreaVector);
11938 : }
11939 4814 : ZoneStruct.NumSurfaceFaces = NActFaces;
11940 4814 : SurfCount = double(NActFaces);
11941 :
11942 : bool isFloorHorizontal;
11943 : bool isCeilingHorizontal;
11944 : bool areWallsVertical;
11945 4814 : std::tie(isFloorHorizontal, isCeilingHorizontal, areWallsVertical) = areSurfaceHorizAndVert(state, ZoneStruct);
11946 : Real64 oppositeWallArea;
11947 : Real64 distanceBetweenOppositeWalls;
11948 :
11949 4814 : bool areWallsSameHeight = areWallHeightSame(state, ZoneStruct);
11950 :
11951 9628 : std::vector<EdgeOfSurf> listOfedgeNotUsedTwice;
11952 4814 : bool isZoneEnclosed = isEnclosedVolume(ZoneStruct, listOfedgeNotUsedTwice);
11953 : ZoneVolumeCalcMethod volCalcMethod;
11954 :
11955 4814 : if (isZoneEnclosed) {
11956 4795 : CalcVolume = CalcPolyhedronVolume(state, ZoneStruct);
11957 4795 : volCalcMethod = ZoneVolumeCalcMethod::Enclosed;
11958 36 : } else if (state.dataHeatBal->Zone(ZoneNum).FloorArea > 0.0 && state.dataHeatBal->Zone(ZoneNum).CeilingHeight > 0.0 &&
11959 17 : areFloorAndCeilingSame(state, ZoneStruct)) {
11960 13 : CalcVolume = state.dataHeatBal->Zone(ZoneNum).FloorArea * state.dataHeatBal->Zone(ZoneNum).CeilingHeight;
11961 13 : volCalcMethod = ZoneVolumeCalcMethod::FloorAreaTimesHeight1;
11962 7 : } else if (isFloorHorizontal && areWallsVertical && areWallsSameHeight && state.dataHeatBal->Zone(ZoneNum).FloorArea > 0.0 &&
11963 1 : state.dataHeatBal->Zone(ZoneNum).CeilingHeight > 0.0) {
11964 1 : CalcVolume = state.dataHeatBal->Zone(ZoneNum).FloorArea * state.dataHeatBal->Zone(ZoneNum).CeilingHeight;
11965 1 : volCalcMethod = ZoneVolumeCalcMethod::FloorAreaTimesHeight2;
11966 5 : } else if (isCeilingHorizontal && areWallsVertical && areWallsSameHeight && state.dataHeatBal->Zone(ZoneNum).CeilingArea > 0.0 &&
11967 0 : state.dataHeatBal->Zone(ZoneNum).CeilingHeight > 0.0) {
11968 0 : CalcVolume = state.dataHeatBal->Zone(ZoneNum).CeilingArea * state.dataHeatBal->Zone(ZoneNum).CeilingHeight;
11969 0 : volCalcMethod = ZoneVolumeCalcMethod::CeilingAreaTimesHeight;
11970 5 : } else if (areOppositeWallsSame(state, ZoneStruct, oppositeWallArea, distanceBetweenOppositeWalls)) {
11971 3 : CalcVolume = oppositeWallArea * distanceBetweenOppositeWalls;
11972 3 : volCalcMethod = ZoneVolumeCalcMethod::OpWallAreaTimesDistance;
11973 2 : } else if (state.dataHeatBal->Zone(ZoneNum).Volume == DataGlobalConstants::AutoCalculate) { // no user entered zone volume
11974 0 : ShowSevereError(state,
11975 0 : "For zone: " + state.dataHeatBal->Zone(ZoneNum).Name +
11976 : " it is not possible to calculate the volume from the surrounding surfaces so either provide the volume value or "
11977 : "define all the surfaces to fully enclose the zone.");
11978 0 : CalcVolume = 0.;
11979 0 : volCalcMethod = ZoneVolumeCalcMethod::Invalid;
11980 : } else {
11981 2 : CalcVolume = 0.;
11982 2 : volCalcMethod = ZoneVolumeCalcMethod::UserProvided;
11983 : }
11984 4814 : if (!isZoneEnclosed) {
11985 19 : ++countNotFullyEnclosedZones;
11986 19 : if (state.dataGlobal->DisplayExtraWarnings) { // report missing
11987 0 : ShowWarningError(state,
11988 0 : "CalculateZoneVolume: The Zone=\"" + state.dataHeatBal->Zone(ZoneNum).Name +
11989 : "\" is not fully enclosed. To be fully enclosed, each edge of a surface must also be an edge on one "
11990 : "other surface.");
11991 0 : switch (volCalcMethod) {
11992 0 : case ZoneVolumeCalcMethod::FloorAreaTimesHeight1:
11993 0 : ShowContinueError(state,
11994 : " The zone volume was calculated using the floor area times ceiling height method where the floor and "
11995 : "ceiling are the same except for the z-coordinates.");
11996 0 : break;
11997 0 : case ZoneVolumeCalcMethod::FloorAreaTimesHeight2:
11998 0 : ShowContinueError(state,
11999 : " The zone volume was calculated using the floor area times ceiling height method where the floor is "
12000 : "horizontal, the walls are vertical, and the wall heights are all the same.");
12001 0 : break;
12002 0 : case ZoneVolumeCalcMethod::CeilingAreaTimesHeight:
12003 0 : ShowContinueError(state,
12004 : " The zone volume was calculated using the ceiling area times ceiling height method where the ceiling is "
12005 : "horizontal, the walls are vertical, and the wall heights are all the same.");
12006 0 : break;
12007 0 : case ZoneVolumeCalcMethod::OpWallAreaTimesDistance:
12008 0 : ShowContinueError(state,
12009 : " The zone volume was calculated using the opposite wall area times the distance between them method ");
12010 0 : break;
12011 0 : case ZoneVolumeCalcMethod::UserProvided:
12012 0 : ShowContinueError(state, " The zone volume was provided as an input to the ZONE object ");
12013 0 : break;
12014 0 : case ZoneVolumeCalcMethod::Invalid:
12015 0 : ShowContinueError(state, " The zone volume was not calculated and an error exists. ");
12016 0 : break;
12017 0 : case ZoneVolumeCalcMethod::Enclosed: // should not be called but completes enumeration
12018 0 : ShowContinueError(state, " The zone volume was calculated using multiple pyramids and was fully enclosed. ");
12019 0 : break;
12020 0 : default:
12021 0 : assert(false);
12022 : }
12023 0 : for (auto &edge : listOfedgeNotUsedTwice) {
12024 0 : if (edge.count < 2) {
12025 0 : ShowContinueError(
12026 : state,
12027 0 : fmt::format(" The surface \"{}\" has an edge that was used only once: it is not an edge on another surface",
12028 0 : state.dataSurface->Surface(edge.surfNum).Name));
12029 :
12030 : } else {
12031 0 : ShowContinueError(
12032 : state,
12033 0 : fmt::format(" The surface \"{}\" has an edge that was used {} times: it is an edge on three or more surfaces: ",
12034 0 : state.dataSurface->Surface(edge.surfNum).Name,
12035 : edge.count));
12036 0 : std::string surfaceNames = " It was found on the following Surfaces: ";
12037 0 : for (int surfNum : edge.otherSurfNums) {
12038 0 : surfaceNames += fmt::format("'{}' ", state.dataSurface->Surface(surfNum).Name);
12039 : }
12040 0 : ShowContinueError(state, surfaceNames);
12041 : }
12042 0 : ShowContinueError(state, format(" Vertex start {{ {:.4R}, {:.4R}, {:.4R}}}", edge.start.x, edge.start.y, edge.start.z));
12043 0 : ShowContinueError(state, format(" Vertex end {{ {:.4R}, {:.4R}, {:.4R}}}", edge.end.x, edge.end.y, edge.end.z));
12044 : }
12045 : }
12046 : }
12047 4814 : if (state.dataHeatBal->Zone(ZoneNum).Volume > 0.0) { // User entered zone volume, produce message if not near calculated
12048 2288 : if (CalcVolume > 0.0) {
12049 2286 : if (std::abs(CalcVolume - state.dataHeatBal->Zone(ZoneNum).Volume) / state.dataHeatBal->Zone(ZoneNum).Volume > 0.05) {
12050 2 : ++ErrCount5;
12051 2 : if (ErrCount5 == 1 && !state.dataGlobal->DisplayExtraWarnings) {
12052 1 : if (initmsg) {
12053 1 : ShowMessage(state,
12054 : "Note that the following warning(s) may/will occur if you have not enclosed your zone completely.");
12055 1 : initmsg = false;
12056 : }
12057 1 : ShowWarningError(state, "Entered Zone Volumes differ from calculated zone volume(s).");
12058 1 : ShowContinueError(state, "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on individual zones.");
12059 : }
12060 2 : if (state.dataGlobal->DisplayExtraWarnings) {
12061 0 : if (initmsg) {
12062 0 : ShowMessage(state,
12063 : "Note that the following warning(s) may/will occur if you have not enclosed your zone completely.");
12064 0 : initmsg = false;
12065 : }
12066 : // Warn user of using specified Zone Volume
12067 0 : ShowWarningError(state,
12068 0 : "Entered Volume entered for Zone=\"" + state.dataHeatBal->Zone(ZoneNum).Name +
12069 : "\" significantly different from calculated Volume");
12070 0 : ShowContinueError(state,
12071 0 : format("Entered Zone Volume value={:.2R}, Calculated Zone Volume value={:.2R}, entered volume will be "
12072 : "used in calculations.",
12073 0 : state.dataHeatBal->Zone(ZoneNum).Volume,
12074 0 : CalcVolume));
12075 : }
12076 : }
12077 : }
12078 2526 : } else if (CeilingHeightEntered(ZoneNum)) { // User did not enter zone volume, but entered ceiling height
12079 123 : if (state.dataHeatBal->Zone(ZoneNum).FloorArea > 0.0) {
12080 123 : state.dataHeatBal->Zone(ZoneNum).Volume =
12081 123 : state.dataHeatBal->Zone(ZoneNum).FloorArea * state.dataHeatBal->Zone(ZoneNum).CeilingHeight;
12082 : } else { // ceiling height entered but floor area zero
12083 0 : state.dataHeatBal->Zone(ZoneNum).Volume = CalcVolume;
12084 : }
12085 : } else { // Neither ceiling height nor volume entered
12086 2403 : state.dataHeatBal->Zone(ZoneNum).Volume = CalcVolume;
12087 : }
12088 :
12089 4814 : if (state.dataHeatBal->Zone(ZoneNum).Volume <= 0.0) {
12090 0 : ShowWarningError(state, "Indicated Zone Volume <= 0.0 for Zone=" + state.dataHeatBal->Zone(ZoneNum).Name);
12091 0 : ShowContinueError(state, format("The calculated Zone Volume was={:.2R}", state.dataHeatBal->Zone(ZoneNum).Volume));
12092 0 : ShowContinueError(state, "The simulation will continue with the Zone Volume set to 10.0 m3. ");
12093 0 : ShowContinueError(state, "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on individual zones.");
12094 0 : state.dataHeatBal->Zone(ZoneNum).Volume = 10.;
12095 : }
12096 : // For now - pro-rate space volumes by floor area, if not entered
12097 9632 : for (int spaceNum : thisZone.spaceIndexes) {
12098 4818 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
12099 : // don't touch if already user-specified
12100 4818 : if (thisSpace.Volume > 0.0) continue;
12101 4818 : if (thisZone.numSpaces == 1) {
12102 4812 : thisSpace.Volume = thisZone.Volume;
12103 6 : } else if (thisZone.FloorArea > 0.0) {
12104 6 : thisSpace.Volume = thisZone.Volume * thisSpace.floorArea / thisZone.FloorArea;
12105 : }
12106 : }
12107 4814 : Real64 totSpacesVolume = 0.0;
12108 9632 : for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
12109 4818 : totSpacesVolume += state.dataHeatBal->space(spaceNum).Volume;
12110 : }
12111 4814 : if (totSpacesVolume > 0.0) {
12112 9632 : for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
12113 4818 : state.dataHeatBal->space(spaceNum).fracZoneVolume = state.dataHeatBal->space(spaceNum).Volume / totSpacesVolume;
12114 : }
12115 : } // else leave fractions at zero
12116 :
12117 4814 : if (ShowZoneSurfaces) {
12118 0 : if (ShowZoneSurfaceHeaders) {
12119 0 : print(state.files.debug, "{}\n", "===================================");
12120 0 : print(state.files.debug, "{}\n", "showing zone surfaces used and not used in volume calculation");
12121 0 : print(state.files.debug, "{}\n", "for volume calculation, only floors, walls and roofs/ceilings are used");
12122 0 : print(state.files.debug, "{}\n", "surface class, 1=wall, 2=floor, 3=roof/ceiling");
12123 0 : print(state.files.debug, "{}\n", "unused surface class(es), 5=internal mass, 11=window, 12=glass door");
12124 0 : print(state.files.debug, "{}\n", " 13=door, 14=shading, 15=overhang, 16=fin");
12125 0 : print(state.files.debug, "{}\n", " 17=TDD Dome, 18=TDD Diffuser");
12126 0 : ShowZoneSurfaceHeaders = false;
12127 : }
12128 0 : print(state.files.debug, "{}\n", "===================================");
12129 0 : print(state.files.debug, "zone={} calc volume={}\n", state.dataHeatBal->Zone(ZoneNum).Name, CalcVolume);
12130 0 : print(state.files.debug, " nsurfaces={} nactual={}\n", NFaces, NActFaces);
12131 : }
12132 38308 : for (SurfNum = 1; SurfNum <= ZoneStruct.NumSurfaceFaces; ++SurfNum) {
12133 33494 : if (ShowZoneSurfaces) {
12134 0 : if (SurfNum <= NActFaces) {
12135 0 : print(state.files.debug,
12136 : "surface={} nsides={}\n",
12137 0 : ZoneStruct.SurfaceFace(SurfNum).SurfNum,
12138 0 : ZoneStruct.SurfaceFace(SurfNum).NSides);
12139 0 : print(state.files.debug,
12140 : "surface name={} class={}\n",
12141 0 : state.dataSurface->Surface(ZoneStruct.SurfaceFace(SurfNum).SurfNum).Name,
12142 0 : state.dataSurface->Surface(ZoneStruct.SurfaceFace(SurfNum).SurfNum).Class);
12143 0 : print(state.files.debug, "area={}\n", state.dataSurface->Surface(ZoneStruct.SurfaceFace(SurfNum).SurfNum).GrossArea);
12144 0 : for (iside = 1; iside <= ZoneStruct.SurfaceFace(SurfNum).NSides; ++iside) {
12145 0 : auto const &FacePoint(ZoneStruct.SurfaceFace(SurfNum).FacePoints(iside));
12146 0 : print(state.files.debug, "{} {} {}\n", FacePoint.x, FacePoint.y, FacePoint.z);
12147 : }
12148 : }
12149 : }
12150 33494 : ZoneStruct.SurfaceFace(SurfNum).FacePoints.deallocate();
12151 : }
12152 4814 : if (ShowZoneSurfaces) {
12153 0 : for (SurfNum = 1; SurfNum <= notused; ++SurfNum) {
12154 0 : print(state.files.debug,
12155 : "notused:surface={} name={} class={}\n",
12156 : surfacenotused(SurfNum),
12157 0 : state.dataSurface->Surface(surfacenotused(SurfNum)).Name,
12158 0 : state.dataSurface->Surface(surfacenotused(SurfNum)).Class);
12159 : }
12160 : }
12161 :
12162 4814 : ZoneStruct.SurfaceFace.deallocate();
12163 4814 : surfacenotused.deallocate();
12164 :
12165 : } // zone loop
12166 771 : if (!state.dataGlobal->DisplayExtraWarnings) {
12167 723 : if (countNotFullyEnclosedZones == 1) {
12168 11 : ShowWarningError(
12169 : state, "CalculateZoneVolume: 1 zone is not fully enclosed. For more details use: Output:Diagnostics,DisplayExtrawarnings; ");
12170 712 : } else if (countNotFullyEnclosedZones > 1) {
12171 12 : ShowWarningError(state,
12172 8 : format("CalculateZoneVolume: {} zones are not fully enclosed. For more details use: "
12173 : "Output:Diagnostics,DisplayExtrawarnings; ",
12174 4 : countNotFullyEnclosedZones));
12175 : }
12176 : }
12177 771 : }
12178 :
12179 : // test if the volume described by the polyhedron if full enclosed (would not leak)
12180 4814 : bool isEnclosedVolume(DataVectorTypes::Polyhedron const &zonePoly, std::vector<EdgeOfSurf> &edgeNot2)
12181 : {
12182 : // J. Glazer - March 2017
12183 :
12184 9628 : std::vector<Vector> uniqueVertices = makeListOfUniqueVertices(zonePoly);
12185 :
12186 9628 : std::vector<EdgeOfSurf> edgeNot2orig = edgesNotTwoForEnclosedVolumeTest(zonePoly, uniqueVertices);
12187 : // if all edges had two counts then it is fully enclosed
12188 4814 : if (edgeNot2orig.empty()) {
12189 3848 : edgeNot2 = edgeNot2orig;
12190 3848 : return true;
12191 : } else { // if the count is three or greater it is likely that a vertex that is colinear was counted on the faces on one edge and not
12192 : // on the "other side" of the edge Go through all the points looking for the number that are colinear and see if that is
12193 : // consistent with the number of edges found that didn't have a count of two
12194 : DataVectorTypes::Polyhedron updatedZonePoly = updateZonePolygonsForMissingColinearPoints(
12195 1932 : zonePoly, uniqueVertices); // this is done after initial test since it is computationally intensive.
12196 1932 : std::vector<EdgeOfSurf> edgeNot2again = edgesNotTwoForEnclosedVolumeTest(updatedZonePoly, uniqueVertices);
12197 966 : if (edgeNot2again.empty()) {
12198 947 : return true;
12199 : } else {
12200 19 : edgeNot2 = edgesInBoth(edgeNot2orig,
12201 : edgeNot2again); // only return a list of those edges that appear in both the original edge and the
12202 : // revised edges this eliminates added edges that will confuse users and edges that
12203 : // were caught by the updateZonePoly routine
12204 19 : return false;
12205 : }
12206 : }
12207 : }
12208 :
12209 : // returns a vector of edges that are in both vectors
12210 19 : std::vector<EdgeOfSurf> edgesInBoth(std::vector<EdgeOfSurf> edges1, std::vector<EdgeOfSurf> edges2)
12211 : {
12212 : // J. Glazer - June 2017
12213 : // this is not optimized but the number of edges for a typical polyhedron is 12 and is probably rarely bigger than 20.
12214 :
12215 19 : std::vector<EdgeOfSurf> inBoth;
12216 251 : for (const auto &e1 : edges1) {
12217 3107 : for (const auto &e2 : edges2) {
12218 3063 : if (edgesEqualOnSameSurface(e1, e2)) {
12219 188 : inBoth.push_back(e1);
12220 188 : break;
12221 : }
12222 : }
12223 : }
12224 19 : return inBoth;
12225 : }
12226 :
12227 : // returns true if the edges match - including the surface number
12228 3063 : bool edgesEqualOnSameSurface(EdgeOfSurf a, EdgeOfSurf b)
12229 : {
12230 3063 : if (a.surfNum != b.surfNum) {
12231 2619 : return false;
12232 : }
12233 :
12234 : // vertex comparison (we compare indices, so absolute equal)
12235 444 : return ((a.start == b.start && a.end == b.end) || (a.start == b.end && a.end == b.start));
12236 : }
12237 :
12238 : // returns the number of times the edges of the polyhedron of the zone are not used twice by the sides
12239 5780 : std::vector<EdgeOfSurf> edgesNotTwoForEnclosedVolumeTest(DataVectorTypes::Polyhedron const &zonePoly, std::vector<Vector> const &uniqueVertices)
12240 : {
12241 : // J. Glazer - March 2017
12242 :
12243 : using DataVectorTypes::Vector;
12244 :
12245 271317 : struct EdgeByPts
12246 : {
12247 : int start;
12248 : int end;
12249 : int count;
12250 : int firstSurfNum;
12251 : std::vector<int> otherSurfNums;
12252 90439 : EdgeByPts() : start(0), end(0), count(0), firstSurfNum(0)
12253 : {
12254 90439 : }
12255 : };
12256 11560 : std::vector<EdgeByPts> uniqueEdges;
12257 5780 : uniqueEdges.reserve(zonePoly.NumSurfaceFaces * 6);
12258 :
12259 : // construct list of unique edges
12260 11560 : Vector curVertex;
12261 : int curVertexIndex;
12262 47553 : for (int iFace = 1; iFace <= zonePoly.NumSurfaceFaces; ++iFace) {
12263 83546 : Vector prevVertex;
12264 : int prevVertexIndex;
12265 213580 : for (int jVertex = 1; jVertex <= zonePoly.SurfaceFace(iFace).NSides; ++jVertex) {
12266 171807 : if (jVertex == 1) {
12267 41773 : prevVertex = zonePoly.SurfaceFace(iFace).FacePoints(zonePoly.SurfaceFace(iFace).NSides); // the last point
12268 41773 : prevVertexIndex = findIndexOfVertex(prevVertex, uniqueVertices);
12269 : } else {
12270 130034 : prevVertex = curVertex;
12271 130034 : prevVertexIndex = curVertexIndex;
12272 : }
12273 171807 : curVertex = zonePoly.SurfaceFace(iFace).FacePoints(jVertex);
12274 171807 : curVertexIndex = findIndexOfVertex(curVertex, uniqueVertices); // uses isAlmostEqual3dPt
12275 5237228 : auto it = std::find_if(uniqueEdges.begin(), uniqueEdges.end(), [&curVertexIndex, &prevVertexIndex](const auto &edge) {
12276 4897511 : return ((edge.start == curVertexIndex && edge.end == prevVertexIndex) ||
12277 3151500 : (edge.start == prevVertexIndex && edge.end == curVertexIndex));
12278 2094730 : });
12279 171807 : if (it == uniqueEdges.end()) {
12280 180878 : EdgeByPts curEdge;
12281 90439 : curEdge.start = prevVertexIndex;
12282 90439 : curEdge.end = curVertexIndex;
12283 90439 : curEdge.count = 1;
12284 90439 : curEdge.firstSurfNum = zonePoly.SurfaceFace(iFace).SurfNum;
12285 90439 : uniqueEdges.emplace_back(curEdge);
12286 : } else {
12287 81368 : ++(it->count);
12288 81368 : it->otherSurfNums.push_back(zonePoly.SurfaceFace(iFace).SurfNum);
12289 : }
12290 : }
12291 : }
12292 : // All edges for an enclosed polyhedron should be shared by two (and only two) sides.
12293 : // So if the count is not two for all edges, the polyhedron is not enclosed
12294 5780 : std::vector<EdgeOfSurf> edgesNotTwoCount;
12295 96219 : for (const auto &anEdge : uniqueEdges) {
12296 90439 : if (anEdge.count != 2) {
12297 18414 : EdgeOfSurf curEdgeOne;
12298 9207 : curEdgeOne.surfNum = anEdge.firstSurfNum;
12299 9207 : curEdgeOne.start = uniqueVertices[anEdge.start];
12300 9207 : curEdgeOne.end = uniqueVertices[anEdge.end];
12301 9207 : curEdgeOne.count = anEdge.count;
12302 9207 : curEdgeOne.otherSurfNums = anEdge.otherSurfNums;
12303 9207 : edgesNotTwoCount.push_back(curEdgeOne);
12304 : }
12305 : }
12306 11560 : return edgesNotTwoCount;
12307 : }
12308 :
12309 : // create a list of unique vertices given the polyhedron describing the zone
12310 4814 : std::vector<Vector> makeListOfUniqueVertices(DataVectorTypes::Polyhedron const &zonePoly)
12311 : {
12312 : // J. Glazer - March 2017
12313 :
12314 : using DataVectorTypes::Vector;
12315 4814 : std::vector<Vector> uniqVertices;
12316 4814 : uniqVertices.reserve(zonePoly.NumSurfaceFaces * 6);
12317 :
12318 38308 : for (int iFace = 1; iFace <= zonePoly.NumSurfaceFaces; ++iFace) {
12319 168189 : for (int jVertex = 1; jVertex <= zonePoly.SurfaceFace(iFace).NSides; ++jVertex) {
12320 269390 : Vector curVertex = zonePoly.SurfaceFace(iFace).FacePoints(jVertex);
12321 134695 : if (uniqVertices.size() == 0) {
12322 4814 : uniqVertices.emplace_back(curVertex);
12323 : } else {
12324 129881 : bool found = false;
12325 781357 : for (const auto &unqV : uniqVertices) {
12326 740748 : if (isAlmostEqual3dPt(curVertex, unqV)) {
12327 89272 : found = true;
12328 89272 : break;
12329 : }
12330 : }
12331 129881 : if (!found) {
12332 40609 : uniqVertices.emplace_back(curVertex);
12333 : }
12334 : }
12335 : }
12336 : }
12337 4814 : return uniqVertices;
12338 : }
12339 :
12340 : // updates the polyhedron used to describe a zone to include points on an edge that are between and collinear to points already describing
12341 : // the edge
12342 966 : DataVectorTypes::Polyhedron updateZonePolygonsForMissingColinearPoints(DataVectorTypes::Polyhedron const &zonePoly,
12343 : std::vector<Vector> const &uniqVertices)
12344 : {
12345 : // J. Glazer - March 2017
12346 :
12347 : using DataVectorTypes::Vector;
12348 :
12349 966 : DataVectorTypes::Polyhedron updZonePoly = zonePoly; // set the return value to the original polyhedron describing the zone
12350 :
12351 10731 : for (auto &updFace : updZonePoly.SurfaceFace) {
12352 9765 : bool insertedVertext = true;
12353 36725 : while (insertedVertext) {
12354 13480 : insertedVertext = false;
12355 13480 : auto &vertices = updFace.FacePoints;
12356 60525 : for (auto it = vertices.begin(); it != vertices.end(); ++it) {
12357 :
12358 50760 : auto itnext = std::next(it);
12359 50760 : if (itnext == std::end(vertices)) {
12360 9531 : itnext = std::begin(vertices);
12361 : }
12362 :
12363 97805 : auto curVertex = *it;
12364 97805 : auto nextVertex = *itnext;
12365 :
12366 : // now go through all the vertices and see if they are colinear with start and end vertices
12367 901865 : for (const auto &testVertex : uniqVertices) {
12368 854820 : if (!isAlmostEqual3dPt(curVertex, testVertex) && !isAlmostEqual3dPt(nextVertex, testVertex)) {
12369 755256 : if (isPointOnLineBetweenPoints(curVertex, nextVertex, testVertex)) {
12370 3715 : vertices.insert(itnext, testVertex);
12371 3715 : ++updFace.NSides;
12372 3715 : insertedVertext = true;
12373 3715 : break;
12374 : }
12375 : }
12376 : }
12377 : // Break out of the loop on vertices of the surface too, and start again at the while
12378 50760 : if (insertedVertext) {
12379 3715 : break;
12380 : }
12381 : }
12382 : }
12383 : }
12384 966 : return updZonePoly;
12385 : }
12386 :
12387 : // test if the ceiling and floor are the same except for their height difference by looking at the corners
12388 17 : bool areFloorAndCeilingSame(EnergyPlusData &state, DataVectorTypes::Polyhedron const &zonePoly)
12389 : {
12390 : // J. Glazer - March 2017
12391 :
12392 : // check if the floor and ceiling are the same
12393 : // this is almost equivalent to saying, if you ignore the z-coordinate, are the vertices the same
12394 : // so if you could all the unique vertices of the floor and ceiling, ignoring the z-coordinate, they
12395 : // should always be even (they would be two but you might define multiple surfaces that meet in a corner)
12396 :
12397 : using DataVectorTypes::Vector;
12398 : using DataVectorTypes::Vector2dCount;
12399 : using DataVectorTypes::Vector_2d;
12400 :
12401 34 : std::vector<Vector2dCount> floorCeilingXY;
12402 17 : floorCeilingXY.reserve(zonePoly.NumSurfaceFaces * 6);
12403 :
12404 : // make list of x and y coordinates for all faces that are on the floor or ceiling
12405 183 : for (int iFace = 1; iFace <= zonePoly.NumSurfaceFaces; ++iFace) {
12406 166 : int curSurfNum = zonePoly.SurfaceFace(iFace).SurfNum;
12407 304 : if (state.dataSurface->Surface(curSurfNum).Class == SurfaceClass::Floor ||
12408 138 : state.dataSurface->Surface(curSurfNum).Class == SurfaceClass::Roof) {
12409 291 : for (int jVertex = 1; jVertex <= zonePoly.SurfaceFace(iFace).NSides; ++jVertex) {
12410 468 : Vector curVertex = zonePoly.SurfaceFace(iFace).FacePoints(jVertex);
12411 468 : Vector2dCount curXYc;
12412 234 : curXYc.x = curVertex.x;
12413 234 : curXYc.y = curVertex.y;
12414 234 : curXYc.count = 1;
12415 234 : bool found = false;
12416 900 : for (Vector2dCount &curFloorCeiling : floorCeilingXY) { // can't use just "auto" because updating floorCeilingXY
12417 790 : if (isAlmostEqual2dPt(curXYc, curFloorCeiling)) { // count ignored in comparison
12418 124 : ++curFloorCeiling.count;
12419 124 : found = true;
12420 124 : break;
12421 : }
12422 : }
12423 234 : if (!found) {
12424 110 : floorCeilingXY.emplace_back(curXYc);
12425 : }
12426 : }
12427 : }
12428 : }
12429 : // now make sure every point has been counted and even number of times (usually twice)
12430 : // if they are then the ceiling and floor are (almost certainly) the same x and y coordinates.
12431 17 : bool areFlrAndClgSame = true;
12432 17 : if (floorCeilingXY.size() > 0) {
12433 91 : for (auto curFloorCeiling : floorCeilingXY) {
12434 78 : if (curFloorCeiling.count % 2 != 0) {
12435 4 : areFlrAndClgSame = false;
12436 4 : break;
12437 : }
12438 : }
12439 : } else {
12440 0 : areFlrAndClgSame = false;
12441 : }
12442 34 : return areFlrAndClgSame;
12443 : }
12444 :
12445 : // test if the walls of a zone are all the same height using the polyhedron describing the zone geometry
12446 4814 : bool areWallHeightSame(EnergyPlusData &state, DataVectorTypes::Polyhedron const &zonePoly)
12447 : {
12448 : // J. Glazer - March 2017
12449 :
12450 : // test if all the wall heights are the same (all walls have the same maximum z-coordinate
12451 :
12452 4814 : bool areWlHgtSame = true;
12453 4814 : Real64 wallHeightZ = -1.0E50;
12454 4814 : bool foundWallHeight = false;
12455 37462 : for (int iFace = 1; iFace <= zonePoly.NumSurfaceFaces; ++iFace) {
12456 32718 : int curSurfNum = zonePoly.SurfaceFace(iFace).SurfNum;
12457 32718 : if (state.dataSurface->Surface(curSurfNum).Class == SurfaceClass::Wall) {
12458 20999 : Real64 maxZ = -1.0E50;
12459 104926 : for (int jVertex = 1; jVertex <= zonePoly.SurfaceFace(iFace).NSides; ++jVertex) {
12460 167854 : Vector curVertex = zonePoly.SurfaceFace(iFace).FacePoints(jVertex);
12461 83927 : if (maxZ < curVertex.z) {
12462 21044 : maxZ = curVertex.z;
12463 : }
12464 : }
12465 20999 : if (foundWallHeight) {
12466 16207 : if (std::abs(maxZ - wallHeightZ) > 0.0254) { // 2.54 cm = 1 inch
12467 70 : areWlHgtSame = false;
12468 70 : break;
12469 : }
12470 : } else {
12471 4792 : wallHeightZ = maxZ;
12472 4792 : foundWallHeight = true;
12473 : }
12474 : }
12475 : }
12476 4814 : return areWlHgtSame;
12477 : }
12478 :
12479 : // tests if the floor is horizontal, ceiling is horizontal, and walls are vertical and returns all three as a tuple of booleans
12480 4814 : std::tuple<bool, bool, bool> areSurfaceHorizAndVert(EnergyPlusData &state, DataVectorTypes::Polyhedron const &zonePoly)
12481 : {
12482 : // J. Glazer - March 2017
12483 :
12484 : // check if floors and ceilings are horizontal and walls are vertical
12485 4814 : bool isFlrHoriz = true;
12486 4814 : bool isClgHoriz = true;
12487 4814 : bool areWlVert = true;
12488 38308 : for (int iFace = 1; iFace <= zonePoly.NumSurfaceFaces; ++iFace) {
12489 33494 : int curSurfNum = zonePoly.SurfaceFace(iFace).SurfNum;
12490 33494 : if (state.dataSurface->Surface(curSurfNum).Class == SurfaceClass::Floor) {
12491 6522 : if (std::abs(state.dataSurface->Surface(curSurfNum).Tilt - 180.) > 1.) { // with 1 degree angle
12492 0 : isFlrHoriz = false;
12493 : }
12494 26972 : } else if (state.dataSurface->Surface(curSurfNum).Class == SurfaceClass::Roof) { // includes ceilings
12495 5490 : if (std::abs(state.dataSurface->Surface(curSurfNum).Tilt) > 1.) { // with 1 degree angle of
12496 250 : isClgHoriz = false;
12497 : }
12498 21482 : } else if (state.dataSurface->Surface(curSurfNum).Class == SurfaceClass::Wall) {
12499 21482 : if (std::abs(state.dataSurface->Surface(curSurfNum).Tilt - 90) > 1.) { // with 1 degree angle
12500 2 : areWlVert = false;
12501 : }
12502 : }
12503 : }
12504 4814 : return std::make_tuple(isFlrHoriz, isClgHoriz, areWlVert);
12505 : }
12506 :
12507 : // tests whether a pair of walls in the zone are the same except offset from one another and facing the opposite direction and also
12508 : // returns the wall area and distance between
12509 5 : bool areOppositeWallsSame(EnergyPlusData &state,
12510 : DataVectorTypes::Polyhedron const &zonePoly,
12511 : Real64 &oppositeWallArea, // return the area of the wall that has an opposite wall
12512 : Real64 &distanceBetweenOppositeWalls // returns distance
12513 : )
12514 : {
12515 : // J. Glazer - March 2017
12516 :
12517 : // approach: if opposite surfaces have opposite azimuth and same area, then check the distance between the
12518 : // vertices( one counting backwards ) and if it is the same distance than assume that it is the same.
12519 : using DataVectorTypes::Vector;
12520 5 : bool foundOppEqual = false;
12521 15 : for (int iFace = 1; iFace <= zonePoly.NumSurfaceFaces; ++iFace) {
12522 13 : int curSurfNum = zonePoly.SurfaceFace(iFace).SurfNum;
12523 13 : if (state.dataSurface->Surface(curSurfNum).Class == SurfaceClass::Wall) {
12524 23 : std::vector<int> facesAtAz = listOfFacesFacingAzimuth(state, zonePoly, state.dataSurface->Surface(curSurfNum).Azimuth);
12525 13 : bool allFacesEquidistant = true;
12526 13 : oppositeWallArea = 0.;
12527 28 : for (auto curFace : facesAtAz) {
12528 25 : int possOppFace = findPossibleOppositeFace(state, zonePoly, curFace);
12529 25 : if (possOppFace > 0) { // an opposite fact was found
12530 16 : oppositeWallArea += state.dataSurface->Surface(zonePoly.SurfaceFace(curFace).SurfNum).Area;
12531 16 : if (!areCornersEquidistant(zonePoly, curFace, possOppFace, distanceBetweenOppositeWalls)) {
12532 1 : allFacesEquidistant = false;
12533 1 : break;
12534 : }
12535 : } else {
12536 9 : allFacesEquidistant = false;
12537 9 : break;
12538 : }
12539 : }
12540 13 : if (allFacesEquidistant) {
12541 3 : foundOppEqual = true;
12542 3 : break; // only need to find the first case where opposite walls are the same
12543 : }
12544 : }
12545 : }
12546 5 : return foundOppEqual;
12547 : }
12548 :
12549 : // provides a list of indices of polyhedron faces that are facing a specific azimuth
12550 13 : std::vector<int> listOfFacesFacingAzimuth(EnergyPlusData &state, DataVectorTypes::Polyhedron const &zonePoly, Real64 const azimuth)
12551 : {
12552 : // J. Glazer - March 2017
12553 :
12554 13 : std::vector<int> facingAzimuth;
12555 13 : facingAzimuth.reserve(zonePoly.NumSurfaceFaces);
12556 :
12557 139 : for (int iFace = 1; iFace <= zonePoly.NumSurfaceFaces; ++iFace) {
12558 126 : int curSurfNum = zonePoly.SurfaceFace(iFace).SurfNum;
12559 126 : if (std::abs(state.dataSurface->Surface(curSurfNum).Azimuth - azimuth) < 1.) {
12560 34 : facingAzimuth.emplace_back(iFace);
12561 : }
12562 : }
12563 13 : return facingAzimuth;
12564 : }
12565 :
12566 : // returns the index of the face of a polyhedron that is probably opposite of the face index provided
12567 25 : int findPossibleOppositeFace(EnergyPlusData &state, DataVectorTypes::Polyhedron const &zonePoly, int const faceIndex)
12568 : {
12569 : // J. Glazer - March 2017
12570 :
12571 25 : int selectedSurNum = zonePoly.SurfaceFace(faceIndex).SurfNum;
12572 25 : Real64 selectedAzimuth = state.dataSurface->Surface(selectedSurNum).Azimuth;
12573 25 : Real64 oppositeAzimuth = fmod(selectedAzimuth + 180., 360.);
12574 25 : Real64 selectedArea = state.dataSurface->Surface(selectedSurNum).Area;
12575 25 : int selectedNumCorners = zonePoly.SurfaceFace(faceIndex).NSides;
12576 25 : int found = -1;
12577 :
12578 160 : for (int iFace = 1; iFace <= zonePoly.NumSurfaceFaces; ++iFace) {
12579 151 : int curSurfNum = zonePoly.SurfaceFace(iFace).SurfNum;
12580 453 : if ((zonePoly.SurfaceFace(iFace).NSides == selectedNumCorners) &&
12581 210 : (std::abs(state.dataSurface->Surface(curSurfNum).Area - selectedArea) < 0.01) &&
12582 59 : (std::abs(state.dataSurface->Surface(curSurfNum).Azimuth - oppositeAzimuth) < 1.)) {
12583 16 : found = iFace;
12584 16 : break;
12585 : }
12586 : }
12587 25 : return found;
12588 : }
12589 :
12590 : // tests if the corners of one face of the polyhedron are the same distance from corners of another face
12591 16 : bool areCornersEquidistant(DataVectorTypes::Polyhedron const &zonePoly, int const faceIndex, int const opFaceIndex, Real64 &distanceBetween)
12592 : {
12593 : // J. Glazer - March 2017
12594 :
12595 16 : Real64 tol = 0.0127; // 1.27 cm = 1/2 inch
12596 16 : bool allAreEquidistant = true;
12597 16 : Real64 firstDistance = -99.;
12598 16 : if (zonePoly.SurfaceFace(faceIndex).NSides == zonePoly.SurfaceFace(opFaceIndex).NSides) { // double check that the number of sides match
12599 78 : for (int iVertex = 1; iVertex <= zonePoly.SurfaceFace(faceIndex).NSides; ++iVertex) {
12600 63 : int iVertexOpp = 1 + zonePoly.SurfaceFace(faceIndex).NSides - iVertex; // count backwards for opposite face
12601 : Real64 curDistBetwCorners =
12602 63 : distance(zonePoly.SurfaceFace(faceIndex).FacePoints(iVertex), zonePoly.SurfaceFace(opFaceIndex).FacePoints(iVertexOpp));
12603 63 : if (iVertex == 1) {
12604 16 : firstDistance = curDistBetwCorners;
12605 : } else {
12606 47 : if (std::abs(curDistBetwCorners - firstDistance) > tol) {
12607 1 : allAreEquidistant = false;
12608 1 : break;
12609 : }
12610 : }
12611 : }
12612 : } else {
12613 0 : allAreEquidistant = false;
12614 : }
12615 16 : if (allAreEquidistant) distanceBetween = firstDistance;
12616 16 : return allAreEquidistant;
12617 : }
12618 :
12619 : // test if two points in space are in the same position based on a small tolerance
12620 19036619 : bool isAlmostEqual3dPt(DataVectorTypes::Vector v1, DataVectorTypes::Vector v2)
12621 : {
12622 : // J. Glazer - March 2017
12623 :
12624 19036619 : Real64 tol = 0.0127; // 1.27 cm = 1/2 inch
12625 19036619 : return ((std::abs(v1.x - v2.x) < tol) && (std::abs(v1.y - v2.y) < tol) && (std::abs(v1.z - v2.z) < tol));
12626 : }
12627 :
12628 : // test if two points on a plane are in the same position based on a small tolerance
12629 790 : bool isAlmostEqual2dPt(DataVectorTypes::Vector_2d v1, DataVectorTypes::Vector_2d v2)
12630 : {
12631 : // J. Glazer - March 2017
12632 :
12633 790 : Real64 tol = 0.0127; // 1.27 cm = 1/2 inch
12634 790 : return ((std::abs(v1.x - v2.x) < tol) && (std::abs(v1.y - v2.y) < tol));
12635 : }
12636 :
12637 : // test if two points on a plane are in the same position based on a small tolerance (based on Vector2dCount comparison)
12638 0 : bool isAlmostEqual2dPt(DataVectorTypes::Vector2dCount v1, DataVectorTypes::Vector2dCount v2)
12639 : {
12640 : // J. Glazer - March 2017
12641 :
12642 0 : Real64 tol = 0.0127; // 1.27 cm = 1/2 inch
12643 0 : return ((std::abs(v1.x - v2.x) < tol) && (std::abs(v1.y - v2.y) < tol));
12644 : }
12645 :
12646 : // returns the index of vertex in a list that is in the same position in space as the given vertex
12647 213580 : int findIndexOfVertex(DataVectorTypes::Vector vertexToFind, std::vector<DataVectorTypes::Vector> listOfVertices)
12648 : {
12649 : // J. Glazer - March 2017
12650 :
12651 1354988 : for (std::size_t i = 0; i < listOfVertices.size(); i++) {
12652 1354988 : if (isAlmostEqual3dPt(listOfVertices[i], vertexToFind)) {
12653 213580 : return i;
12654 : }
12655 : }
12656 0 : return -1;
12657 : }
12658 :
12659 : // returns the distance between two points in space
12660 1013377 : Real64 distance(DataVectorTypes::Vector v1, DataVectorTypes::Vector v2)
12661 : {
12662 : // J. Glazer - March 2017
12663 :
12664 1013377 : return sqrt(pow(v1.x - v2.x, 2) + pow(v1.y - v2.y, 2) + pow(v1.z - v2.z, 2));
12665 : }
12666 :
12667 6788151 : Real64 distanceFromPointToLine(DataVectorTypes::Vector start, DataVectorTypes::Vector end, DataVectorTypes::Vector test)
12668 : {
12669 : // np.linalg.norm(np.cross(e-s,p-s)/np.linalg.norm(e-s))
12670 13576302 : DataVectorTypes::Vector t = end - start;
12671 6788151 : t.normalize(); // Unit vector of start to end
12672 :
12673 13576302 : DataVectorTypes::Vector other = test - start;
12674 :
12675 13576302 : DataVectorTypes::Vector projection = DataVectorTypes::cross(t, other); // normal unit vector, that's the distance component
12676 13576302 : return projection.length();
12677 : }
12678 :
12679 : // tests if a point in space lies on the line segment defined by two other points
12680 6788151 : bool isPointOnLineBetweenPoints(DataVectorTypes::Vector start, DataVectorTypes::Vector end, DataVectorTypes::Vector test)
12681 : {
12682 : // J. Glazer - March 2017
12683 : // The tolerance has to be low enough. Take for eg a plenum that has an edge that's 30meters long, you risk adding point from the
12684 : // floor to the roof, cf #7383 compute the shortest distance from the point to the line first to avoid false positive
12685 6788151 : Real64 tol = 0.0127;
12686 6788151 : if (distanceFromPointToLine(start, end, test) < tol) { // distanceFromPointToLine always positive, it's calculated as norml_L2
12687 281433 : return (std::abs((distance(start, end) - (distance(start, test) + distance(test, end)))) < tol);
12688 : }
12689 6506718 : return false;
12690 : }
12691 :
12692 1348559 : bool EdgeOfSurf::operator==(const EdgeOfSurf &other) const
12693 : {
12694 6727832 : return ((isAlmostEqual3dPt(this->start, other.start) && isAlmostEqual3dPt(this->end, other.end)) ||
12695 6732636 : (isAlmostEqual3dPt(this->start, other.end) && isAlmostEqual3dPt(this->end, other.start)));
12696 : }
12697 :
12698 0 : bool EdgeOfSurf::operator!=(const EdgeOfSurf &other) const
12699 : {
12700 0 : return !(*this == other);
12701 : }
12702 :
12703 6110750 : bool EdgeOfSurf::containsPoints(const Vector &vertex) const
12704 : {
12705 36353080 : return (!isAlmostEqual3dPt(this->start, vertex) && !isAlmostEqual3dPt(this->end, vertex) &&
12706 36353080 : isPointOnLineBetweenPoints(this->start, this->end, vertex));
12707 : }
12708 :
12709 6964 : double EdgeOfSurf::length() const
12710 : {
12711 6964 : return distance(this->start, this->end);
12712 : }
12713 :
12714 41478 : void ProcessSurfaceVertices(EnergyPlusData &state, int const ThisSurf, bool &ErrorsFound)
12715 : {
12716 :
12717 : // SUBROUTINE INFORMATION:
12718 : // AUTHOR Legacy Code (Walton)
12719 : // DATE WRITTEN 1976
12720 : // MODIFIED FW, Mar 2002: Add triangular windows
12721 : // FW, May 2002: modify test for 4-sided but non-rectangular subsurfaces
12722 : // FW, Sep 2002: add shape for base surfaces (walls and detached shading surfaces)
12723 :
12724 : // PURPOSE OF THIS SUBROUTINE:
12725 : // This subroutine processes each surface into the vertex representation used
12726 : // by the shading procedures.
12727 :
12728 : // METHODOLOGY EMPLOYED:
12729 : // Detached Shading, Base Surfaces, Attached Shading surfaces are represented in the
12730 : // same manner as original. Subsurfaces (windows, doors) are a "relative coordinate".
12731 :
12732 : using namespace Vectors;
12733 :
12734 : static constexpr std::string_view RoutineName("ProcessSurfaceVertices: ");
12735 :
12736 : Real64 X1; // Intermediate Result
12737 : Real64 Y1; // Intermediate Result
12738 : Real64 Z1; // Intermediate Result
12739 : Real64 XLLC; // X-coordinate of lower left corner
12740 : Real64 YLLC; // Y-coordinate of lower left corner
12741 : Real64 ZLLC; // Z-coordinate of lower left corner
12742 : int n; // Vertex Number in Loop
12743 : int ThisBaseSurface; // Current base surface
12744 : Real64 Xp;
12745 : Real64 Yp;
12746 : Real64 Zp;
12747 : Real64 SurfWorldAz; // Surface Azimuth (facing)
12748 : Real64 SurfTilt; // Surface Tilt
12749 41478 : SurfaceShape ThisShape(SurfaceShape::None);
12750 : bool BaseSurface; // True if a base surface or a detached shading surface
12751 : Real64 ThisSurfAz;
12752 : Real64 ThisSurfTilt;
12753 : Real64 ThisReveal;
12754 : Real64 ThisWidth;
12755 : Real64 ThisHeight;
12756 : int FrDivNum; // Frame/divider number
12757 : Real64 FrWidth; // Frame width for exterior windows (m)
12758 : Real64 FrArea; // Frame area for exterior windows(m2)
12759 : Real64 DivWidth; // Divider width for exterior windows (m)
12760 : Real64 DivArea; // Divider area for exterior windows (m2)
12761 : Real64 DivFrac; // Fraction of divider area without overlaps
12762 : bool ErrorInSurface; // false/true, depending on pass through routine
12763 : bool SError; // Bool used for return value of calls to PlaneEquation
12764 : bool HeatTransSurf;
12765 : bool IsCoPlanar;
12766 : Real64 OutOfLine;
12767 : int LastVertexInError;
12768 :
12769 : // Object Data
12770 41478 : PlaneEq BasePlane;
12771 82956 : Vector TVect;
12772 82956 : Vector CoordinateTransVector;
12773 :
12774 41478 : if (state.dataSurface->Surface(ThisSurf).VerticesProcessed) {
12775 0 : return;
12776 : }
12777 :
12778 41478 : ErrorInSurface = false;
12779 :
12780 41478 : if (state.dataSurfaceGeometry->ProcessSurfaceVerticesOneTimeFlag) {
12781 742 : state.dataSurfaceGeometry->Xpsv.allocate(state.dataSurface->MaxVerticesPerSurface);
12782 742 : state.dataSurfaceGeometry->Ypsv.allocate(state.dataSurface->MaxVerticesPerSurface);
12783 742 : state.dataSurfaceGeometry->Zpsv.allocate(state.dataSurface->MaxVerticesPerSurface);
12784 742 : state.dataSurfaceGeometry->Xpsv = 0.0;
12785 742 : state.dataSurfaceGeometry->Ypsv = 0.0;
12786 742 : state.dataSurfaceGeometry->Zpsv = 0.0;
12787 742 : state.dataSurfaceGeometry->ProcessSurfaceVerticesOneTimeFlag = false;
12788 : }
12789 :
12790 : // Categorize this surface
12791 :
12792 41478 : if (state.dataSurface->Surface(ThisSurf).BaseSurf == 0 || state.dataSurface->Surface(ThisSurf).BaseSurf == ThisSurf) {
12793 35038 : BaseSurface = true;
12794 : } else {
12795 6440 : BaseSurface = false;
12796 : }
12797 :
12798 41478 : ThisBaseSurface = state.dataSurface->Surface(ThisSurf).BaseSurf; // Dont know if this is still needed or not
12799 41478 : HeatTransSurf = state.dataSurface->Surface(ThisSurf).HeatTransSurf;
12800 :
12801 : // Kludge for daylighting shelves
12802 41478 : if (state.dataSurface->Surface(ThisSurf).IsShadowing) {
12803 1542 : ThisBaseSurface = ThisSurf;
12804 1542 : HeatTransSurf = true;
12805 : }
12806 :
12807 : // IF (Surface(ThisSurf)%Name(1:3) /= 'Mir') THEN
12808 41478 : if (!state.dataSurface->Surface(ThisSurf).MirroredSurf) {
12809 81414 : CalcCoPlanarNess(
12810 81414 : state.dataSurface->Surface(ThisSurf).Vertex, state.dataSurface->Surface(ThisSurf).Sides, IsCoPlanar, OutOfLine, LastVertexInError);
12811 40707 : if (!IsCoPlanar) {
12812 0 : if (OutOfLine > 0.01) {
12813 0 : ShowSevereError(state,
12814 0 : format("{}Suspected non-planar surface:\"{}\", Max \"out of line\"={:.5T} at Vertex # {}",
12815 : RoutineName,
12816 0 : state.dataSurface->Surface(ThisSurf).Name,
12817 : OutOfLine,
12818 0 : LastVertexInError));
12819 : } else {
12820 0 : ShowWarningError(state,
12821 0 : format("{}Possible non-planar surface:\"{}\", Max \"out of line\"={:.5T} at Vertex # {}",
12822 : RoutineName,
12823 0 : state.dataSurface->Surface(ThisSurf).Name,
12824 : OutOfLine,
12825 0 : LastVertexInError));
12826 : }
12827 : // ErrorInSurface=.TRUE.
12828 : }
12829 : }
12830 :
12831 41478 : if (BaseSurface) {
12832 35038 : SurfWorldAz = state.dataSurface->Surface(ThisSurf).Azimuth;
12833 35038 : SurfTilt = state.dataSurface->Surface(ThisSurf).Tilt;
12834 175865 : for (n = 1; n <= state.dataSurface->Surface(ThisSurf).Sides; ++n) {
12835 140827 : state.dataSurfaceGeometry->Xpsv(n) = state.dataSurface->Surface(ThisSurf).Vertex(n).x;
12836 140827 : state.dataSurfaceGeometry->Ypsv(n) = state.dataSurface->Surface(ThisSurf).Vertex(n).y;
12837 140827 : state.dataSurfaceGeometry->Zpsv(n) = state.dataSurface->Surface(ThisSurf).Vertex(n).z;
12838 : }
12839 35038 : TVect = state.dataSurface->Surface(ThisSurf).Vertex(3) - state.dataSurface->Surface(ThisSurf).Vertex(2);
12840 35038 : ThisWidth = VecLength(TVect);
12841 35038 : TVect = state.dataSurface->Surface(ThisSurf).Vertex(2) - state.dataSurface->Surface(ThisSurf).Vertex(1);
12842 35038 : ThisHeight = VecLength(TVect);
12843 35038 : state.dataSurface->Surface(ThisSurf).Width = ThisWidth;
12844 35038 : state.dataSurface->Surface(ThisSurf).Height = ThisHeight; // For a horizontal surface this is actually length!
12845 35038 : if (state.dataSurface->Surface(ThisSurf).Sides == 3) {
12846 181 : state.dataSurface->Surface(ThisSurf).Shape = SurfaceShape::Triangle;
12847 34857 : } else if (state.dataSurface->Surface(ThisSurf).Sides == 4) {
12848 : // Test for rectangularity
12849 34690 : if (isRectangle(state, ThisSurf)) {
12850 29804 : state.dataSurface->Surface(ThisSurf).Shape = SurfaceShape::Rectangle;
12851 : } else {
12852 4886 : state.dataSurface->Surface(ThisSurf).Shape = SurfaceShape::Quadrilateral;
12853 : }
12854 : } else { // Surface( ThisSurf ).Sides > 4
12855 167 : state.dataSurface->Surface(ThisSurf).Shape = SurfaceShape::Polygonal;
12856 167 : if (std::abs(ThisHeight * ThisWidth - state.dataSurface->Surface(ThisSurf).GrossArea) > 0.001) {
12857 167 : state.dataSurface->Surface(ThisSurf).Width = std::sqrt(state.dataSurface->Surface(ThisSurf).GrossArea);
12858 167 : state.dataSurface->Surface(ThisSurf).Height = state.dataSurface->Surface(ThisSurf).Width;
12859 167 : ThisWidth = state.dataSurface->Surface(ThisSurf).Width;
12860 167 : ThisHeight = state.dataSurface->Surface(ThisSurf).Height;
12861 : }
12862 : }
12863 :
12864 : } else { // It's a subsurface to previous basesurface in this set of calls
12865 :
12866 6440 : ThisSurfAz = state.dataSurface->Surface(ThisSurf).Azimuth;
12867 6440 : ThisSurfTilt = state.dataSurface->Surface(ThisSurf).Tilt;
12868 :
12869 : // Retrieve base surface info
12870 6440 : Real64 const baseSurfWorldAz = state.dataSurface->Surface(ThisBaseSurface).Azimuth;
12871 6440 : Real64 const baseSurfTilt = state.dataSurface->Surface(ThisBaseSurface).Tilt;
12872 6440 : Real64 const BaseCosAzimuth = std::cos(baseSurfWorldAz * DataGlobalConstants::DegToRadians);
12873 6440 : Real64 const BaseSinAzimuth = std::sin(baseSurfWorldAz * DataGlobalConstants::DegToRadians);
12874 6440 : Real64 const BaseCosTilt = std::cos(baseSurfTilt * DataGlobalConstants::DegToRadians);
12875 6440 : Real64 const BaseSinTilt = std::sin(baseSurfTilt * DataGlobalConstants::DegToRadians);
12876 6440 : Real64 const BaseXLLC = state.dataSurface->Surface(ThisBaseSurface).Vertex(2).x;
12877 6440 : Real64 const BaseYLLC = state.dataSurface->Surface(ThisBaseSurface).Vertex(2).y;
12878 6440 : Real64 const BaseZLLC = state.dataSurface->Surface(ThisBaseSurface).Vertex(2).z;
12879 :
12880 6440 : if (HeatTransSurf) {
12881 :
12882 6440 : if (state.dataSurface->Surface(ThisSurf).Sides == 4) {
12883 6438 : ThisShape = SurfaceShape::RectangularDoorWindow;
12884 2 : } else if (state.dataSurface->Surface(ThisSurf).Sides == 3 && state.dataSurface->Surface(ThisSurf).Class == SurfaceClass::Window) {
12885 2 : ThisShape = SurfaceShape::TriangularWindow;
12886 0 : } else if (state.dataSurface->Surface(ThisSurf).Sides == 3 && state.dataSurface->Surface(ThisSurf).Class == SurfaceClass::Door) {
12887 0 : ThisShape = SurfaceShape::TriangularDoor;
12888 : } else {
12889 0 : assert(false);
12890 : }
12891 :
12892 : } else { // this is a shadowing subsurface
12893 :
12894 0 : if (std::abs(state.dataSurface->Surface(state.dataSurface->Surface(ThisSurf).BaseSurf).Tilt - ThisSurfTilt) <= 0.01) {
12895 : // left or right fin
12896 0 : if (ThisSurfAz < 0.0) ThisSurfAz += 360.0;
12897 0 : if (ThisSurfAz > state.dataSurface->Surface(state.dataSurface->Surface(ThisSurf).BaseSurf).Azimuth) {
12898 0 : ThisShape = SurfaceShape::RectangularLeftFin;
12899 : } else {
12900 0 : ThisShape = SurfaceShape::RectangularRightFin;
12901 : }
12902 : } else {
12903 0 : ThisShape = SurfaceShape::RectangularOverhang;
12904 : }
12905 : }
12906 :
12907 : // Setting relative coordinates for shadowing calculations for subsurfaces
12908 6440 : switch (ThisShape) {
12909 6438 : case SurfaceShape::RectangularDoorWindow: { // Rectangular heat transfer subsurface
12910 6438 : PlaneEquation(state.dataSurface->Surface(state.dataSurface->Surface(ThisSurf).BaseSurf).Vertex,
12911 6438 : state.dataSurface->Surface(state.dataSurface->Surface(ThisSurf).BaseSurf).Sides,
12912 : BasePlane,
12913 : SError);
12914 6438 : if (SError) {
12915 0 : ShowSevereError(state,
12916 0 : std::string{RoutineName} + "Degenerate surface (likely two vertices equal):\"" +
12917 0 : state.dataSurface->Surface(ThisSurf).Name + "\".");
12918 0 : ErrorInSurface = true;
12919 : }
12920 6438 : ThisReveal = -Pt2Plane(state.dataSurface->Surface(ThisSurf).Vertex(2), BasePlane);
12921 6438 : if (std::abs(ThisReveal) < 0.0002) ThisReveal = 0.0;
12922 6438 : state.dataSurface->Surface(ThisSurf).Reveal = ThisReveal;
12923 6438 : Xp = state.dataSurface->Surface(ThisSurf).Vertex(2).x - BaseXLLC;
12924 6438 : Yp = state.dataSurface->Surface(ThisSurf).Vertex(2).y - BaseYLLC;
12925 6438 : Zp = state.dataSurface->Surface(ThisSurf).Vertex(2).z - BaseZLLC;
12926 6438 : XLLC = -Xp * BaseCosAzimuth + Yp * BaseSinAzimuth;
12927 6438 : YLLC = -Xp * BaseSinAzimuth * BaseCosTilt - Yp * BaseCosAzimuth * BaseCosTilt + Zp * BaseSinTilt;
12928 6438 : ZLLC = Xp * BaseSinAzimuth * BaseSinTilt + Yp * BaseCosAzimuth * BaseSinTilt + Zp * BaseCosTilt;
12929 6438 : TVect = state.dataSurface->Surface(ThisSurf).Vertex(3) - state.dataSurface->Surface(ThisSurf).Vertex(2);
12930 6438 : ThisWidth = VecLength(TVect);
12931 6438 : TVect = state.dataSurface->Surface(ThisSurf).Vertex(2) - state.dataSurface->Surface(ThisSurf).Vertex(1);
12932 6438 : ThisHeight = VecLength(TVect);
12933 6438 : state.dataSurface->Surface(ThisSurf).Width = ThisWidth;
12934 6438 : state.dataSurface->Surface(ThisSurf).Height = ThisHeight;
12935 :
12936 : // Processing of 4-sided but non-rectangular Window, Door or GlassDoor, for use in calc of convective air flow.
12937 6438 : if (!isRectangle(state, ThisSurf)) {
12938 :
12939 : // Transform the surface into an equivalent rectangular surface with the same area and aspect ratio.
12940 1 : MakeEquivalentRectangle(state, ThisSurf, ErrorsFound);
12941 :
12942 1 : if (state.dataGlobal->DisplayExtraWarnings) {
12943 0 : ShowWarningError(state, std::string{RoutineName} + "Suspected 4-sided but non-rectangular Window, Door or GlassDoor:");
12944 0 : ShowContinueError(state,
12945 0 : "Surface=" + state.dataSurface->Surface(ThisSurf).Name +
12946 : " is transformed into an equivalent rectangular surface with the same area and aspect ratio. ");
12947 : }
12948 : }
12949 :
12950 6438 : state.dataSurfaceGeometry->Xpsv(1) = XLLC;
12951 6438 : state.dataSurfaceGeometry->Xpsv(2) = XLLC;
12952 6438 : state.dataSurfaceGeometry->Xpsv(3) = XLLC + state.dataSurface->Surface(ThisSurf).Width;
12953 6438 : state.dataSurfaceGeometry->Xpsv(4) = XLLC + state.dataSurface->Surface(ThisSurf).Width;
12954 6438 : state.dataSurfaceGeometry->Ypsv(1) = YLLC + state.dataSurface->Surface(ThisSurf).Height;
12955 6438 : state.dataSurfaceGeometry->Ypsv(4) = YLLC + state.dataSurface->Surface(ThisSurf).Height;
12956 6438 : state.dataSurfaceGeometry->Ypsv(2) = YLLC;
12957 6438 : state.dataSurfaceGeometry->Ypsv(3) = YLLC;
12958 6438 : state.dataSurfaceGeometry->Zpsv(1) = ZLLC;
12959 6438 : state.dataSurfaceGeometry->Zpsv(2) = ZLLC;
12960 6438 : state.dataSurfaceGeometry->Zpsv(3) = ZLLC;
12961 6438 : state.dataSurfaceGeometry->Zpsv(4) = ZLLC;
12962 :
12963 18848 : if (state.dataSurface->Surface(ThisSurf).Class == SurfaceClass::Window &&
12964 12396 : state.dataSurface->Surface(ThisSurf).ExtBoundCond == ExternalEnvironment &&
12965 5958 : state.dataSurface->Surface(ThisSurf).FrameDivider > 0) {
12966 381 : FrDivNum = state.dataSurface->Surface(ThisSurf).FrameDivider;
12967 : // Set flag for calculating beam solar reflection from outside and/or inside window reveal
12968 1143 : if ((state.dataSurface->Surface(ThisSurf).Reveal > 0.0 && state.dataSurface->FrameDivider(FrDivNum).OutsideRevealSolAbs > 0.0) ||
12969 381 : (state.dataSurface->FrameDivider(FrDivNum).InsideSillDepth > 0.0 &&
12970 762 : state.dataSurface->FrameDivider(FrDivNum).InsideSillSolAbs > 0.0) ||
12971 381 : (state.dataSurface->FrameDivider(FrDivNum).InsideReveal > 0.0 &&
12972 0 : state.dataSurface->FrameDivider(FrDivNum).InsideRevealSolAbs > 0.0))
12973 0 : state.dataHeatBal->CalcWindowRevealReflection = true;
12974 :
12975 : // For exterior window with frame, subtract frame area from base surface
12976 : // (only rectangular windows are allowed to have a frame and/or divider;
12977 : // Surface(ThisSurf)%FrameDivider will be 0 for triangular windows)
12978 381 : FrWidth = state.dataSurface->FrameDivider(FrDivNum).FrameWidth;
12979 381 : if (FrWidth > 0.0) {
12980 390 : FrArea = (state.dataSurface->Surface(ThisSurf).Height + 2.0 * FrWidth) *
12981 130 : (state.dataSurface->Surface(ThisSurf).Width + 2.0 * FrWidth) -
12982 130 : state.dataSurface->Surface(ThisSurf).Area / state.dataSurface->Surface(ThisSurf).Multiplier;
12983 130 : state.dataSurface->SurfWinFrameArea(ThisSurf) = FrArea * state.dataSurface->Surface(ThisSurf).Multiplier;
12984 390 : if ((state.dataSurface->Surface(state.dataSurface->Surface(ThisSurf).BaseSurf).Area -
12985 260 : state.dataSurface->SurfWinFrameArea(ThisSurf)) <= 0.0) {
12986 0 : ShowSevereError(state,
12987 0 : std::string{RoutineName} + "Base Surface=\"" +
12988 0 : state.dataSurface->Surface(state.dataSurface->Surface(ThisSurf).BaseSurf).Name + "\", ");
12989 0 : ShowContinueError(state,
12990 0 : "Window Surface=\"" + state.dataSurface->Surface(ThisSurf).Name +
12991 : "\" area (with frame) is too large to fit on the surface.");
12992 0 : ShowContinueError(state,
12993 0 : format("Base surface area (-windows and doors)=[{:.2T}] m2, frame area=[{:.2T}] m2.",
12994 0 : state.dataSurface->Surface(state.dataSurface->Surface(ThisSurf).BaseSurf).Area,
12995 0 : state.dataSurface->SurfWinFrameArea(ThisSurf)));
12996 0 : ErrorInSurface = true;
12997 : }
12998 130 : state.dataSurface->Surface(state.dataSurface->Surface(ThisSurf).BaseSurf).Area -=
12999 130 : state.dataSurface->SurfWinFrameArea(ThisSurf);
13000 : }
13001 : // If exterior window has divider, subtract divider area to get glazed area
13002 381 : DivWidth = state.dataSurface->FrameDivider(state.dataSurface->Surface(ThisSurf).FrameDivider).DividerWidth;
13003 381 : if (DivWidth > 0.0 && !ErrorInSurface) {
13004 192 : DivArea = DivWidth * (state.dataSurface->FrameDivider(FrDivNum).HorDividers * state.dataSurface->Surface(ThisSurf).Width +
13005 128 : state.dataSurface->FrameDivider(FrDivNum).VertDividers * state.dataSurface->Surface(ThisSurf).Height -
13006 128 : state.dataSurface->FrameDivider(FrDivNum).HorDividers *
13007 128 : state.dataSurface->FrameDivider(FrDivNum).VertDividers * DivWidth);
13008 64 : state.dataSurface->SurfWinDividerArea(ThisSurf) = DivArea * state.dataSurface->Surface(ThisSurf).Multiplier;
13009 64 : if ((state.dataSurface->Surface(ThisSurf).Area - state.dataSurface->SurfWinDividerArea(ThisSurf)) <= 0.0) {
13010 0 : ShowSevereError(state,
13011 0 : std::string{RoutineName} + "Divider area exceeds glazed opening for window " +
13012 0 : state.dataSurface->Surface(ThisSurf).Name);
13013 0 : ShowContinueError(state,
13014 0 : format("Window surface area=[{:.2T}] m2, divider area=[{:.2T}] m2.",
13015 0 : state.dataSurface->Surface(ThisSurf).Area,
13016 0 : state.dataSurface->SurfWinDividerArea(ThisSurf)));
13017 0 : ErrorInSurface = true;
13018 : }
13019 64 : state.dataSurface->Surface(ThisSurf).Area -= state.dataSurface->SurfWinDividerArea(ThisSurf); // Glazed area
13020 64 : if (DivArea <= 0.0) {
13021 0 : ShowWarningError(state,
13022 0 : std::string{RoutineName} +
13023 0 : "Calculated Divider Area <= 0.0 for Window=" + state.dataSurface->Surface(ThisSurf).Name);
13024 0 : if (state.dataSurface->FrameDivider(FrDivNum).HorDividers == 0) {
13025 0 : ShowContinueError(state, "..Number of Horizontal Dividers = 0.");
13026 : }
13027 0 : if (state.dataSurface->FrameDivider(FrDivNum).VertDividers == 0) {
13028 0 : ShowContinueError(state, "..Number of Vertical Dividers = 0.");
13029 : }
13030 : } else {
13031 64 : state.dataSurface->SurfWinGlazedFrac(ThisSurf) =
13032 128 : state.dataSurface->Surface(ThisSurf).Area /
13033 64 : (state.dataSurface->Surface(ThisSurf).Area + state.dataSurface->SurfWinDividerArea(ThisSurf));
13034 : // Correction factor for portion of divider subject to divider projection correction
13035 192 : DivFrac = (1.0 - state.dataSurface->FrameDivider(FrDivNum).HorDividers *
13036 128 : state.dataSurface->FrameDivider(FrDivNum).VertDividers * pow_2(DivWidth) / DivArea);
13037 64 : state.dataSurface->SurfWinProjCorrDivOut(ThisSurf) =
13038 64 : DivFrac * state.dataSurface->FrameDivider(FrDivNum).DividerProjectionOut / DivWidth;
13039 64 : state.dataSurface->SurfWinProjCorrDivIn(ThisSurf) =
13040 64 : DivFrac * state.dataSurface->FrameDivider(FrDivNum).DividerProjectionIn / DivWidth;
13041 : // Correction factor for portion of frame subject to frame projection correction
13042 64 : if (FrWidth > 0.0) {
13043 64 : state.dataSurface->SurfWinProjCorrFrOut(ThisSurf) =
13044 128 : (state.dataSurface->FrameDivider(FrDivNum).FrameProjectionOut / FrWidth) *
13045 128 : (ThisHeight + ThisWidth -
13046 128 : (state.dataSurface->FrameDivider(FrDivNum).HorDividers +
13047 128 : state.dataSurface->FrameDivider(FrDivNum).VertDividers) *
13048 64 : DivWidth) /
13049 64 : (ThisHeight + ThisWidth + 2 * FrWidth);
13050 64 : state.dataSurface->SurfWinProjCorrFrIn(ThisSurf) =
13051 128 : (state.dataSurface->FrameDivider(FrDivNum).FrameProjectionIn / FrWidth) *
13052 128 : (ThisHeight + ThisWidth -
13053 128 : (state.dataSurface->FrameDivider(FrDivNum).HorDividers +
13054 128 : state.dataSurface->FrameDivider(FrDivNum).VertDividers) *
13055 64 : DivWidth) /
13056 64 : (ThisHeight + ThisWidth + 2 * FrWidth);
13057 : }
13058 : }
13059 : }
13060 : }
13061 6438 : } break;
13062 2 : case SurfaceShape::TriangularWindow:
13063 : case SurfaceShape::TriangularDoor: {
13064 2 : PlaneEquation(state.dataSurface->Surface(state.dataSurface->Surface(ThisSurf).BaseSurf).Vertex,
13065 2 : state.dataSurface->Surface(state.dataSurface->Surface(ThisSurf).BaseSurf).Sides,
13066 : BasePlane,
13067 : SError);
13068 2 : if (SError) {
13069 0 : ShowSevereError(state,
13070 0 : std::string{RoutineName} + "Degenerate surface (likely two vertices equal):\"" +
13071 0 : state.dataSurface->Surface(ThisSurf).Name + "\".");
13072 0 : ErrorInSurface = true;
13073 : }
13074 2 : ThisReveal = -Pt2Plane(state.dataSurface->Surface(ThisSurf).Vertex(2), BasePlane);
13075 2 : if (std::abs(ThisReveal) < 0.0002) ThisReveal = 0.0;
13076 2 : state.dataSurface->Surface(ThisSurf).Reveal = ThisReveal;
13077 2 : Xp = state.dataSurface->Surface(ThisSurf).Vertex(2).x - BaseXLLC;
13078 2 : Yp = state.dataSurface->Surface(ThisSurf).Vertex(2).y - BaseYLLC;
13079 2 : Zp = state.dataSurface->Surface(ThisSurf).Vertex(2).z - BaseZLLC;
13080 2 : state.dataSurfaceGeometry->Xpsv(2) = -Xp * BaseCosAzimuth + Yp * BaseSinAzimuth;
13081 2 : state.dataSurfaceGeometry->Ypsv(2) = -Xp * BaseSinAzimuth * BaseCosTilt - Yp * BaseCosAzimuth * BaseCosTilt + Zp * BaseSinTilt;
13082 2 : state.dataSurfaceGeometry->Zpsv(2) = Xp * BaseSinAzimuth * BaseSinTilt + Yp * BaseCosAzimuth * BaseSinTilt + Zp * BaseCosTilt;
13083 2 : TVect = state.dataSurface->Surface(ThisSurf).Vertex(3) - state.dataSurface->Surface(ThisSurf).Vertex(2);
13084 2 : ThisWidth = VecLength(TVect);
13085 2 : TVect = state.dataSurface->Surface(ThisSurf).Vertex(2) - state.dataSurface->Surface(ThisSurf).Vertex(1);
13086 2 : ThisHeight = VecLength(TVect);
13087 2 : state.dataSurface->Surface(ThisSurf).Width = ThisWidth;
13088 2 : state.dataSurface->Surface(ThisSurf).Height = ThisHeight;
13089 : // Effective height and width of a triangular window for use in calc of convective air flow
13090 : // in gap between glass and shading device when shading device is present
13091 2 : state.dataSurface->Surface(ThisSurf).Height =
13092 2 : 4.0 * state.dataSurface->Surface(ThisSurf).Area / (3.0 * state.dataSurface->Surface(ThisSurf).Width);
13093 2 : state.dataSurface->Surface(ThisSurf).Width *= 0.75;
13094 :
13095 2 : Xp = state.dataSurface->Surface(ThisSurf).Vertex(1).x - BaseXLLC;
13096 2 : Yp = state.dataSurface->Surface(ThisSurf).Vertex(1).y - BaseYLLC;
13097 2 : Zp = state.dataSurface->Surface(ThisSurf).Vertex(1).z - BaseZLLC;
13098 2 : state.dataSurfaceGeometry->Xpsv(1) = -Xp * BaseCosAzimuth + Yp * BaseSinAzimuth;
13099 2 : state.dataSurfaceGeometry->Ypsv(1) = -Xp * BaseSinAzimuth * BaseCosTilt - Yp * BaseCosAzimuth * BaseCosTilt + Zp * BaseSinTilt;
13100 2 : state.dataSurfaceGeometry->Zpsv(1) = Xp * BaseSinAzimuth * BaseSinTilt + Yp * BaseCosAzimuth * BaseSinTilt + Zp * BaseCosTilt;
13101 :
13102 2 : Xp = state.dataSurface->Surface(ThisSurf).Vertex(3).x - BaseXLLC;
13103 2 : Yp = state.dataSurface->Surface(ThisSurf).Vertex(3).y - BaseYLLC;
13104 2 : Zp = state.dataSurface->Surface(ThisSurf).Vertex(3).z - BaseZLLC;
13105 2 : state.dataSurfaceGeometry->Xpsv(3) = -Xp * BaseCosAzimuth + Yp * BaseSinAzimuth;
13106 2 : state.dataSurfaceGeometry->Ypsv(3) = -Xp * BaseSinAzimuth * BaseCosTilt - Yp * BaseCosAzimuth * BaseCosTilt + Zp * BaseSinTilt;
13107 2 : state.dataSurfaceGeometry->Zpsv(3) = Xp * BaseSinAzimuth * BaseSinTilt + Yp * BaseCosAzimuth * BaseSinTilt + Zp * BaseCosTilt;
13108 2 : } break;
13109 0 : case SurfaceShape::RectangularOverhang: {
13110 0 : Xp = state.dataSurface->Surface(ThisSurf).Vertex(2).x - BaseXLLC;
13111 0 : Yp = state.dataSurface->Surface(ThisSurf).Vertex(2).y - BaseYLLC;
13112 0 : Zp = state.dataSurface->Surface(ThisSurf).Vertex(2).z - BaseZLLC;
13113 0 : XLLC = -Xp * BaseCosAzimuth + Yp * BaseSinAzimuth;
13114 0 : YLLC = -Xp * BaseSinAzimuth * BaseCosTilt - Yp * BaseCosAzimuth * BaseCosTilt + Zp * BaseSinTilt;
13115 0 : ZLLC = Xp * BaseSinAzimuth * BaseSinTilt + Yp * BaseCosAzimuth * BaseSinTilt + Zp * BaseCosTilt;
13116 0 : TVect = state.dataSurface->Surface(ThisSurf).Vertex(3) - state.dataSurface->Surface(ThisSurf).Vertex(2);
13117 0 : ThisWidth = VecLength(TVect);
13118 0 : TVect = state.dataSurface->Surface(ThisSurf).Vertex(2) - state.dataSurface->Surface(ThisSurf).Vertex(1);
13119 0 : ThisHeight = VecLength(TVect);
13120 0 : state.dataSurface->Surface(ThisSurf).Width = ThisWidth;
13121 0 : state.dataSurface->Surface(ThisSurf).Height = ThisHeight;
13122 0 : state.dataSurfaceGeometry->Xpsv(1) = XLLC;
13123 0 : state.dataSurfaceGeometry->Xpsv(2) = XLLC;
13124 0 : state.dataSurfaceGeometry->Xpsv(3) = XLLC + state.dataSurface->Surface(ThisSurf).Width;
13125 0 : state.dataSurfaceGeometry->Xpsv(4) = XLLC + state.dataSurface->Surface(ThisSurf).Width;
13126 0 : state.dataSurfaceGeometry->Ypsv(1) = YLLC;
13127 0 : state.dataSurfaceGeometry->Ypsv(2) = YLLC;
13128 0 : state.dataSurfaceGeometry->Ypsv(3) = YLLC;
13129 0 : state.dataSurfaceGeometry->Ypsv(4) = YLLC;
13130 0 : state.dataSurfaceGeometry->Zpsv(1) = state.dataSurface->Surface(ThisSurf).Height;
13131 0 : state.dataSurfaceGeometry->Zpsv(4) = state.dataSurface->Surface(ThisSurf).Height;
13132 0 : state.dataSurfaceGeometry->Zpsv(2) = 0.0;
13133 0 : state.dataSurfaceGeometry->Zpsv(3) = 0.0;
13134 0 : } break;
13135 0 : case SurfaceShape::RectangularLeftFin: {
13136 0 : Xp = state.dataSurface->Surface(ThisSurf).Vertex(2).x - BaseXLLC;
13137 0 : Yp = state.dataSurface->Surface(ThisSurf).Vertex(2).y - BaseYLLC;
13138 0 : Zp = state.dataSurface->Surface(ThisSurf).Vertex(2).z - BaseZLLC;
13139 0 : XLLC = -Xp * BaseCosAzimuth + Yp * BaseSinAzimuth;
13140 0 : YLLC = -Xp * BaseSinAzimuth * BaseCosTilt - Yp * BaseCosAzimuth * BaseCosTilt + Zp * BaseSinTilt;
13141 0 : ZLLC = Xp * BaseSinAzimuth * BaseSinTilt + Yp * BaseCosAzimuth * BaseSinTilt + Zp * BaseCosTilt;
13142 0 : TVect = state.dataSurface->Surface(ThisSurf).Vertex(3) - state.dataSurface->Surface(ThisSurf).Vertex(2);
13143 0 : ThisWidth = VecLength(TVect);
13144 0 : TVect = state.dataSurface->Surface(ThisSurf).Vertex(2) - state.dataSurface->Surface(ThisSurf).Vertex(1);
13145 0 : ThisHeight = VecLength(TVect);
13146 0 : state.dataSurface->Surface(ThisSurf).Width = ThisWidth;
13147 0 : state.dataSurface->Surface(ThisSurf).Height = ThisHeight;
13148 0 : state.dataSurfaceGeometry->Xpsv(1) = XLLC;
13149 0 : state.dataSurfaceGeometry->Xpsv(2) = XLLC;
13150 0 : state.dataSurfaceGeometry->Xpsv(3) = XLLC;
13151 0 : state.dataSurfaceGeometry->Xpsv(4) = XLLC;
13152 0 : state.dataSurfaceGeometry->Ypsv(1) = YLLC;
13153 0 : state.dataSurfaceGeometry->Ypsv(2) = YLLC;
13154 0 : state.dataSurfaceGeometry->Ypsv(3) = YLLC + state.dataSurface->Surface(ThisSurf).Width;
13155 0 : state.dataSurfaceGeometry->Ypsv(4) = YLLC + state.dataSurface->Surface(ThisSurf).Width;
13156 0 : state.dataSurfaceGeometry->Zpsv(1) = state.dataSurface->Surface(ThisSurf).Height;
13157 0 : state.dataSurfaceGeometry->Zpsv(4) = state.dataSurface->Surface(ThisSurf).Height;
13158 0 : state.dataSurfaceGeometry->Zpsv(2) = 0.0;
13159 0 : state.dataSurfaceGeometry->Zpsv(3) = 0.0;
13160 0 : } break;
13161 0 : case SurfaceShape::RectangularRightFin: {
13162 0 : Xp = state.dataSurface->Surface(ThisSurf).Vertex(2).x - BaseXLLC;
13163 0 : Yp = state.dataSurface->Surface(ThisSurf).Vertex(2).y - BaseYLLC;
13164 0 : Zp = state.dataSurface->Surface(ThisSurf).Vertex(2).z - BaseZLLC;
13165 0 : XLLC = -Xp * BaseCosAzimuth + Yp * BaseSinAzimuth;
13166 0 : YLLC = -Xp * BaseSinAzimuth * BaseCosTilt - Yp * BaseCosAzimuth * BaseCosTilt + Zp * BaseSinTilt;
13167 0 : ZLLC = Xp * BaseSinAzimuth * BaseSinTilt + Yp * BaseCosAzimuth * BaseSinTilt + Zp * BaseCosTilt;
13168 0 : TVect = state.dataSurface->Surface(ThisSurf).Vertex(3) - state.dataSurface->Surface(ThisSurf).Vertex(2);
13169 0 : ThisWidth = VecLength(TVect);
13170 0 : TVect = state.dataSurface->Surface(ThisSurf).Vertex(2) - state.dataSurface->Surface(ThisSurf).Vertex(1);
13171 0 : ThisHeight = VecLength(TVect);
13172 0 : state.dataSurface->Surface(ThisSurf).Width = ThisWidth;
13173 0 : state.dataSurface->Surface(ThisSurf).Height = ThisHeight;
13174 0 : state.dataSurfaceGeometry->Xpsv(1) = XLLC;
13175 0 : state.dataSurfaceGeometry->Xpsv(2) = XLLC;
13176 0 : state.dataSurfaceGeometry->Xpsv(3) = XLLC;
13177 0 : state.dataSurfaceGeometry->Xpsv(4) = XLLC;
13178 0 : state.dataSurfaceGeometry->Ypsv(1) = YLLC + state.dataSurface->Surface(ThisSurf).Width;
13179 0 : state.dataSurfaceGeometry->Ypsv(2) = YLLC + state.dataSurface->Surface(ThisSurf).Width;
13180 0 : state.dataSurfaceGeometry->Ypsv(3) = YLLC;
13181 0 : state.dataSurfaceGeometry->Ypsv(4) = YLLC;
13182 0 : state.dataSurfaceGeometry->Zpsv(1) = state.dataSurface->Surface(ThisSurf).Height;
13183 0 : state.dataSurfaceGeometry->Zpsv(4) = state.dataSurface->Surface(ThisSurf).Height;
13184 0 : state.dataSurfaceGeometry->Zpsv(2) = 0.0;
13185 0 : state.dataSurfaceGeometry->Zpsv(3) = 0.0;
13186 0 : } break;
13187 0 : default: {
13188 : // Error Condition
13189 0 : ShowSevereError(state, std::string{RoutineName} + "Incorrect surface shape number.", OptionalOutputFileRef{state.files.eso});
13190 0 : ShowContinueError(state, "Please notify EnergyPlus support of this error and send input file.");
13191 0 : ErrorInSurface = true;
13192 0 : } break;
13193 : }
13194 :
13195 32198 : for (n = 1; n <= state.dataSurface->Surface(ThisSurf).Sides; ++n) {
13196 : // if less than 1/10 inch
13197 25758 : state.dataSurfaceGeometry->Xpsv(n) = nint64(10000.0 * state.dataSurfaceGeometry->Xpsv(n)) / 10000.0;
13198 25758 : if (std::abs(state.dataSurfaceGeometry->Xpsv(n)) < 0.0025) state.dataSurfaceGeometry->Xpsv(n) = 0.0;
13199 25758 : state.dataSurfaceGeometry->Ypsv(n) = nint64(10000.0 * state.dataSurfaceGeometry->Ypsv(n)) / 10000.0;
13200 25758 : if (std::abs(state.dataSurfaceGeometry->Ypsv(n)) < 0.0025) state.dataSurfaceGeometry->Ypsv(n) = 0.0;
13201 25758 : state.dataSurfaceGeometry->Zpsv(n) = nint64(10000.0 * state.dataSurfaceGeometry->Zpsv(n)) / 10000.0;
13202 25758 : if (std::abs(state.dataSurfaceGeometry->Zpsv(n)) < 0.0025) state.dataSurfaceGeometry->Zpsv(n) = 0.0;
13203 : }
13204 :
13205 6440 : state.dataSurface->Surface(ThisSurf).Shape = ThisShape;
13206 :
13207 : } // End of check if ThisSurf is a base surface
13208 :
13209 41478 : if (ErrorInSurface) {
13210 0 : ErrorsFound = true;
13211 0 : return;
13212 : }
13213 :
13214 : // Transfer to XV,YV,ZV arrays
13215 :
13216 41478 : state.dataSurface->ShadeV(ThisSurf).NVert = state.dataSurface->Surface(ThisSurf).Sides;
13217 41478 : state.dataSurface->ShadeV(ThisSurf).XV.allocate(state.dataSurface->Surface(ThisSurf).Sides);
13218 41478 : state.dataSurface->ShadeV(ThisSurf).YV.allocate(state.dataSurface->Surface(ThisSurf).Sides);
13219 41478 : state.dataSurface->ShadeV(ThisSurf).ZV.allocate(state.dataSurface->Surface(ThisSurf).Sides);
13220 :
13221 208063 : for (n = 1; n <= state.dataSurface->Surface(ThisSurf).Sides; ++n) {
13222 : // if less than 1/10 inch
13223 166585 : state.dataSurface->ShadeV(ThisSurf).XV(n) = state.dataSurfaceGeometry->Xpsv(n);
13224 166585 : state.dataSurface->ShadeV(ThisSurf).YV(n) = state.dataSurfaceGeometry->Ypsv(n);
13225 166585 : state.dataSurface->ShadeV(ThisSurf).ZV(n) = state.dataSurfaceGeometry->Zpsv(n);
13226 : }
13227 :
13228 : // Process Surfaces According to Type of Coordinate Origin.
13229 41478 : if (BaseSurface) {
13230 :
13231 : // General Surfaces:
13232 35038 : CalcCoordinateTransformation(state, ThisSurf, CoordinateTransVector); // X00,Y00,Z00,X,Y,Z,A) ! Compute Coordinate Transformation
13233 :
13234 : // RECORD DIRECTION COSINES.
13235 35038 : if (HeatTransSurf) { // This is a general surface but not detached shading surface
13236 :
13237 : // RECORD COORDINATE TRANSFORMATION FOR BASE SURFACES.
13238 35024 : state.dataSurface->X0(ThisBaseSurface) = CoordinateTransVector.x;
13239 35024 : state.dataSurface->Y0(ThisBaseSurface) = CoordinateTransVector.y;
13240 35024 : state.dataSurface->Z0(ThisBaseSurface) = CoordinateTransVector.z;
13241 :
13242 : // COMPUTE INVERSE TRANSFORMATION.
13243 35024 : X1 = state.dataSurfaceGeometry->Xpsv(2) - CoordinateTransVector.x;
13244 35024 : Y1 = state.dataSurfaceGeometry->Ypsv(2) - CoordinateTransVector.y;
13245 35024 : Z1 = state.dataSurfaceGeometry->Zpsv(2) - CoordinateTransVector.z;
13246 : // Store the relative coordinate shift values for later use by any subsurfaces
13247 105072 : state.dataSurface->Surface(ThisBaseSurface).XShift = state.dataSurface->Surface(ThisBaseSurface).lcsx.x * X1 +
13248 70048 : state.dataSurface->Surface(ThisBaseSurface).lcsx.y * Y1 +
13249 35024 : state.dataSurface->Surface(ThisBaseSurface).lcsx.z * Z1;
13250 105072 : state.dataSurface->Surface(ThisBaseSurface).YShift = state.dataSurface->Surface(ThisBaseSurface).lcsy.x * X1 +
13251 70048 : state.dataSurface->Surface(ThisBaseSurface).lcsy.y * Y1 +
13252 35024 : state.dataSurface->Surface(ThisBaseSurface).lcsy.z * Z1;
13253 35024 : state.dataSurface->Surface(ThisBaseSurface).VerticesProcessed = true;
13254 : }
13255 :
13256 : // SUBSURFACES: (Surface(ThisSurf)%BaseSurf /= ThisSurf)
13257 : } else {
13258 : // WINDOWS OR DOORS:
13259 :
13260 : // SHIFT RELATIVE COORDINATES FROM LOWER LEFT CORNER TO ORIGIN DEFINED
13261 : // BY CTRAN AND SET DIRECTION COSINES SAME AS BASE SURFACE.
13262 6440 : if (!state.dataSurface->Surface(ThisBaseSurface).VerticesProcessed) {
13263 :
13264 0 : if (state.dataSurface->Surface(ThisSurf).IsAirBoundarySurf) {
13265 0 : ProcessSurfaceVertices(state, ThisBaseSurface, ErrorsFound);
13266 : } else {
13267 :
13268 0 : ShowSevereError(state, std::string{RoutineName} + "Developer error for Subsurface=" + state.dataSurface->Surface(ThisSurf).Name);
13269 0 : ShowContinueError(state,
13270 0 : "Base surface=" + state.dataSurface->Surface(ThisBaseSurface).Name +
13271 : " vertices must be processed before any subsurfaces.");
13272 0 : ShowFatalError(state, std::string{RoutineName});
13273 : }
13274 : }
13275 :
13276 32198 : for (n = 1; n <= state.dataSurface->Surface(ThisSurf).Sides; ++n) {
13277 25758 : state.dataSurface->ShadeV(ThisSurf).XV(n) += state.dataSurface->Surface(ThisBaseSurface).XShift;
13278 25758 : state.dataSurface->ShadeV(ThisSurf).YV(n) += state.dataSurface->Surface(ThisBaseSurface).YShift;
13279 : }
13280 : }
13281 :
13282 41478 : if (ErrorInSurface) {
13283 0 : ErrorsFound = true;
13284 : }
13285 : }
13286 :
13287 35038 : void CalcCoordinateTransformation(EnergyPlusData &state,
13288 : int const SurfNum, // Surface Number
13289 : Vector &CompCoordTranslVector // Coordinate Translation Vector
13290 : )
13291 : {
13292 :
13293 : // SUBROUTINE INFORMATION:
13294 : // AUTHOR George Walton, BLAST
13295 : // DATE WRITTEN August 1976
13296 : // MODIFIED LKL, May 2004 -- >4 sided polygons
13297 : // RE-ENGINEERED Yes
13298 :
13299 : // PURPOSE OF THIS SUBROUTINE:
13300 : // This subroutine develops a coordinate transformation such that the X-axis goes
13301 : // through points 2 and 3 and the Y-axis goes through point 1
13302 : // of a plane figure in 3-d space.
13303 :
13304 : // METHODOLOGY EMPLOYED:
13305 : // na
13306 :
13307 : // REFERENCES:
13308 : // 'NECAP' - NASA'S Energy-Cost Analysis Program
13309 :
13310 : // Using/Aliasing
13311 : using namespace Vectors;
13312 :
13313 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
13314 : int I; // Loop Control
13315 : Real64 Gamma; // Intermediate Result
13316 : Real64 DotSelfX23;
13317 :
13318 : // Object Data
13319 70076 : Vector x21;
13320 70076 : Vector x23;
13321 :
13322 : // Determine Components of the Coordinate Translation Vector.
13323 :
13324 35038 : x21 = state.dataSurface->Surface(SurfNum).Vertex(2) - state.dataSurface->Surface(SurfNum).Vertex(1);
13325 35038 : x23 = state.dataSurface->Surface(SurfNum).Vertex(2) - state.dataSurface->Surface(SurfNum).Vertex(3);
13326 :
13327 35038 : DotSelfX23 = magnitude_squared(x23);
13328 :
13329 35038 : if (DotSelfX23 <= .1e-6) {
13330 0 : ShowSevereError(state,
13331 0 : "CalcCoordinateTransformation: Invalid dot product, surface=\"" + state.dataSurface->Surface(SurfNum).Name + "\":");
13332 0 : for (I = 1; I <= state.dataSurface->Surface(SurfNum).Sides; ++I) {
13333 0 : auto const &point{state.dataSurface->Surface(SurfNum).Vertex(I)};
13334 0 : ShowContinueError(state, format(" ({:8.3F},{:8.3F},{:8.3F})", point.x, point.y, point.z));
13335 : }
13336 0 : ShowFatalError(
13337 0 : state, "CalcCoordinateTransformation: Program terminates due to preceding condition.", OptionalOutputFileRef{state.files.eso});
13338 0 : return;
13339 : }
13340 :
13341 35038 : Gamma = dot(x21, x23) / magnitude_squared(x23);
13342 :
13343 35038 : CompCoordTranslVector = state.dataSurface->Surface(SurfNum).Vertex(2) +
13344 70076 : Gamma * (state.dataSurface->Surface(SurfNum).Vertex(3) - state.dataSurface->Surface(SurfNum).Vertex(2));
13345 : }
13346 :
13347 18 : void CreateShadedWindowConstruction(EnergyPlusData &state,
13348 : int const SurfNum, // Surface number
13349 : int const WSCPtr, // Pointer to WindowShadingControl for SurfNum
13350 : int const ShDevNum, // Shading device material number for WSCptr
13351 : int const shadeControlIndex // index to the Surface().windowShadingControlList,
13352 : // Surface().shadedConstructionList, and Surface().shadedStormWinConstructionList
13353 : )
13354 : {
13355 :
13356 : // SUBROUTINE INFORMATION:
13357 : // AUTHOR Fred Winkelmann
13358 : // DATE WRITTEN Nov 2001
13359 : // MODIFIED na
13360 : // RE-ENGINEERED na
13361 :
13362 : // PURPOSE OF THIS SUBROUTINE:
13363 : // Creates a shaded window construction for windows whose WindowShadingControl
13364 : // has a shading device specified instead of a shaded construction
13365 :
13366 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
13367 : int ConstrNum; // Number of unshaded construction
13368 : int ConstrNewSh; // Number of shaded construction that is created
13369 36 : std::string ShDevName; // Shading device material name
13370 36 : std::string ConstrName; // Unshaded construction name
13371 36 : std::string ConstrNameSh; // Shaded construction name
13372 : int TotLayersOld; // Total layers in old (unshaded) construction
13373 : int TotLayersNew; // Total layers in new (shaded) construction
13374 : // INTEGER :: loop ! DO loop index
13375 :
13376 18 : ShDevName = state.dataMaterial->Material(ShDevNum).Name;
13377 18 : ConstrNum = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction;
13378 18 : ConstrName = state.dataConstruction->Construct(ConstrNum).Name;
13379 18 : if (ANY_INTERIOR_SHADE_BLIND(state.dataSurface->WindowShadingControl(WSCPtr).ShadingType)) {
13380 18 : ConstrNameSh = ConstrName + ':' + ShDevName + ":INT";
13381 : } else {
13382 0 : ConstrNameSh = ConstrName + ':' + ShDevName + ":EXT";
13383 : }
13384 :
13385 : // If this construction name already exists, set the surface's shaded construction number to it
13386 :
13387 18 : ConstrNewSh = UtilityRoutines::FindItemInList(ConstrNameSh, state.dataConstruction->Construct);
13388 :
13389 18 : if (ConstrNewSh > 0) {
13390 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).shadedConstructionList[shadeControlIndex] = ConstrNewSh;
13391 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeShadedConstruction = ConstrNewSh; // set the active to the current for now
13392 : } else {
13393 :
13394 : // Create new construction
13395 :
13396 18 : ConstrNewSh = state.dataHeatBal->TotConstructs + 1;
13397 18 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).shadedConstructionList[shadeControlIndex] = ConstrNewSh;
13398 18 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeShadedConstruction = ConstrNewSh; // set the active to the current for now
13399 18 : state.dataHeatBal->TotConstructs = ConstrNewSh;
13400 18 : state.dataConstruction->Construct.redimension(state.dataHeatBal->TotConstructs);
13401 18 : state.dataHeatBal->NominalRforNominalUCalculation.redimension(state.dataHeatBal->TotConstructs);
13402 18 : state.dataHeatBal->NominalRforNominalUCalculation(state.dataHeatBal->TotConstructs) = 0.0;
13403 18 : state.dataHeatBal->NominalU.redimension(state.dataHeatBal->TotConstructs);
13404 18 : state.dataHeatBal->NominalU(state.dataHeatBal->TotConstructs) = 0.0;
13405 18 : state.dataHeatBal->NominalUBeforeAdjusted.redimension(state.dataHeatBal->TotConstructs);
13406 18 : state.dataHeatBal->CoeffAdjRatio.redimension(state.dataHeatBal->TotConstructs) = 1.0;
13407 :
13408 18 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).setArraysBasedOnMaxSolidWinLayers(state);
13409 :
13410 18 : TotLayersOld = state.dataConstruction->Construct(ConstrNum).TotLayers;
13411 18 : TotLayersNew = TotLayersOld + 1;
13412 :
13413 18 : state.dataConstruction->Construct(ConstrNewSh).LayerPoint = 0;
13414 :
13415 18 : if (state.dataSurface->WindowShadingControl(WSCPtr).ShadingType == WinShadingType::IntShade ||
13416 0 : state.dataSurface->WindowShadingControl(WSCPtr).ShadingType == WinShadingType::IntBlind) {
13417 : // Interior shading device
13418 18 : state.dataConstruction->Construct(ConstrNewSh).LayerPoint({1, TotLayersOld}) =
13419 36 : state.dataConstruction->Construct(ConstrNum).LayerPoint({1, TotLayersOld});
13420 18 : state.dataConstruction->Construct(ConstrNewSh).LayerPoint(TotLayersNew) = ShDevNum;
13421 18 : state.dataConstruction->Construct(ConstrNewSh).InsideAbsorpSolar = state.dataMaterial->Material(ShDevNum).AbsorpSolar;
13422 18 : state.dataConstruction->Construct(ConstrNewSh).OutsideAbsorpSolar =
13423 18 : state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNewSh).LayerPoint(1)).AbsorpSolar;
13424 18 : state.dataConstruction->Construct(ConstrNewSh).OutsideAbsorpThermal =
13425 18 : state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNewSh).LayerPoint(1)).AbsorpThermalFront;
13426 : } else {
13427 : // Exterior shading device
13428 0 : state.dataConstruction->Construct(ConstrNewSh).LayerPoint(1) = ShDevNum;
13429 0 : state.dataConstruction->Construct(ConstrNewSh).LayerPoint({2, TotLayersNew}) =
13430 0 : state.dataConstruction->Construct(ConstrNum).LayerPoint({1, TotLayersOld});
13431 0 : state.dataConstruction->Construct(ConstrNewSh).InsideAbsorpSolar =
13432 0 : state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNewSh).LayerPoint(TotLayersNew)).AbsorpSolar;
13433 0 : state.dataConstruction->Construct(ConstrNewSh).OutsideAbsorpSolar = state.dataMaterial->Material(ShDevNum).AbsorpSolar;
13434 0 : state.dataConstruction->Construct(ConstrNewSh).OutsideAbsorpThermal = state.dataMaterial->Material(ShDevNum).AbsorpThermalFront;
13435 : }
13436 : // The following InsideAbsorpThermal applies only to inside glass; it is corrected
13437 : // later in InitGlassOpticalCalculations if construction has inside shade or blind.
13438 18 : state.dataConstruction->Construct(ConstrNewSh).InsideAbsorpThermal =
13439 18 : state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNum).LayerPoint(TotLayersOld)).AbsorpThermalBack;
13440 18 : state.dataConstruction->Construct(ConstrNewSh).OutsideRoughness = DataSurfaces::SurfaceRoughness::VerySmooth;
13441 18 : state.dataConstruction->Construct(ConstrNewSh).DayltPropPtr = 0;
13442 18 : state.dataConstruction->Construct(ConstrNewSh).CTFCross = 0.0;
13443 18 : state.dataConstruction->Construct(ConstrNewSh).CTFFlux = 0.0;
13444 18 : state.dataConstruction->Construct(ConstrNewSh).CTFInside = 0.0;
13445 18 : state.dataConstruction->Construct(ConstrNewSh).CTFOutside = 0.0;
13446 18 : state.dataConstruction->Construct(ConstrNewSh).CTFSourceIn = 0.0;
13447 18 : state.dataConstruction->Construct(ConstrNewSh).CTFSourceOut = 0.0;
13448 18 : state.dataConstruction->Construct(ConstrNewSh).CTFTimeStep = 0.0;
13449 18 : state.dataConstruction->Construct(ConstrNewSh).CTFTSourceOut = 0.0;
13450 18 : state.dataConstruction->Construct(ConstrNewSh).CTFTSourceIn = 0.0;
13451 18 : state.dataConstruction->Construct(ConstrNewSh).CTFTSourceQ = 0.0;
13452 18 : state.dataConstruction->Construct(ConstrNewSh).CTFTUserOut = 0.0;
13453 18 : state.dataConstruction->Construct(ConstrNewSh).CTFTUserIn = 0.0;
13454 18 : state.dataConstruction->Construct(ConstrNewSh).CTFTUserSource = 0.0;
13455 18 : state.dataConstruction->Construct(ConstrNewSh).NumHistories = 0;
13456 18 : state.dataConstruction->Construct(ConstrNewSh).NumCTFTerms = 0;
13457 18 : state.dataConstruction->Construct(ConstrNewSh).UValue = 0.0;
13458 18 : state.dataConstruction->Construct(ConstrNewSh).SourceSinkPresent = false;
13459 18 : state.dataConstruction->Construct(ConstrNewSh).SolutionDimensions = 0;
13460 18 : state.dataConstruction->Construct(ConstrNewSh).SourceAfterLayer = 0;
13461 18 : state.dataConstruction->Construct(ConstrNewSh).TempAfterLayer = 0;
13462 18 : state.dataConstruction->Construct(ConstrNewSh).ThicknessPerpend = 0.0;
13463 18 : state.dataConstruction->Construct(ConstrNewSh).AbsDiff = 0.0;
13464 18 : state.dataConstruction->Construct(ConstrNewSh).AbsDiffBack = 0.0;
13465 18 : state.dataConstruction->Construct(ConstrNewSh).AbsDiffShade = 0.0;
13466 18 : state.dataConstruction->Construct(ConstrNewSh).AbsDiffBackShade = 0.0;
13467 18 : state.dataConstruction->Construct(ConstrNewSh).ShadeAbsorpThermal = 0.0;
13468 18 : state.dataConstruction->Construct(ConstrNewSh).AbsBeamShadeCoef = 0.0;
13469 18 : state.dataConstruction->Construct(ConstrNewSh).TransDiff = 0.0;
13470 18 : state.dataConstruction->Construct(ConstrNewSh).TransDiffVis = 0.0;
13471 18 : state.dataConstruction->Construct(ConstrNewSh).ReflectSolDiffBack = 0.0;
13472 18 : state.dataConstruction->Construct(ConstrNewSh).ReflectSolDiffFront = 0.0;
13473 18 : state.dataConstruction->Construct(ConstrNewSh).ReflectVisDiffBack = 0.0;
13474 18 : state.dataConstruction->Construct(ConstrNewSh).ReflectVisDiffFront = 0.0;
13475 18 : state.dataConstruction->Construct(ConstrNewSh).TransSolBeamCoef = 0.0;
13476 18 : state.dataConstruction->Construct(ConstrNewSh).TransVisBeamCoef = 0.0;
13477 18 : state.dataConstruction->Construct(ConstrNewSh).ReflSolBeamFrontCoef = 0.0;
13478 18 : state.dataConstruction->Construct(ConstrNewSh).ReflSolBeamBackCoef = 0.0;
13479 18 : state.dataConstruction->Construct(ConstrNewSh).W5FrameDivider = 0;
13480 18 : state.dataConstruction->Construct(ConstrNewSh).FromWindow5DataFile = false;
13481 :
13482 18 : state.dataConstruction->Construct(ConstrNewSh).Name = ConstrNameSh;
13483 18 : state.dataConstruction->Construct(ConstrNewSh).TotLayers = TotLayersNew;
13484 18 : state.dataConstruction->Construct(ConstrNewSh).TotSolidLayers = state.dataConstruction->Construct(ConstrNum).TotSolidLayers + 1;
13485 18 : state.dataConstruction->Construct(ConstrNewSh).TotGlassLayers = state.dataConstruction->Construct(ConstrNum).TotGlassLayers;
13486 18 : state.dataConstruction->Construct(ConstrNewSh).TypeIsWindow = true;
13487 18 : state.dataConstruction->Construct(ConstrNewSh).IsUsed = true;
13488 :
13489 144 : for (int Layer = 1; Layer <= state.dataHeatBal->MaxSolidWinLayers; ++Layer) {
13490 882 : for (int index = 1; index <= DataSurfaces::MaxPolyCoeff; ++index) {
13491 756 : state.dataConstruction->Construct(ConstrNewSh).AbsBeamCoef(Layer)(index) = 0.0;
13492 756 : state.dataConstruction->Construct(ConstrNewSh).AbsBeamBackCoef(Layer)(index) = 0.0;
13493 : }
13494 : }
13495 : }
13496 18 : }
13497 :
13498 1 : void CreateStormWindowConstructions(EnergyPlusData &state)
13499 : {
13500 : // For windows with an associated StormWindow object, creates a construction
13501 : // consisting of the base construction plus a storm window and air gap on the outside.
13502 : // If the window has an interior or between-glass shade/blind, also creates a
13503 : // construction consisting of the storm window added to the shaded construction.
13504 1 : DisplayString(state, "Creating Storm Window Constructions");
13505 :
13506 2 : for (int StormWinNum = 1; StormWinNum <= state.dataSurface->TotStormWin; ++StormWinNum) {
13507 1 : int SurfNum = state.dataSurface->StormWindow(StormWinNum).BaseWindowNum; // Surface number
13508 1 : int ConstrNum = state.dataSurface->Surface(SurfNum).Construction; // Number of unshaded construction
13509 : // Fatal error if base construction has more than three glass layers
13510 1 : if (state.dataConstruction->Construct(ConstrNum).TotGlassLayers > 3) {
13511 0 : ShowFatalError(
13512 0 : state, "Window=" + state.dataSurface->Surface(SurfNum).Name + " has more than 3 glass layers; a storm window cannot be applied.");
13513 : }
13514 :
13515 : // create unshaded construction with storm window
13516 2 : const auto ChrNum = fmt::to_string(StormWinNum);
13517 2 : std::string ConstrNameSt = "BARECONSTRUCTIONWITHSTORMWIN:" + ChrNum; // Name of unshaded construction with storm window
13518 : // If this construction name already exists, set the surface's storm window construction number to it
13519 : int ConstrNewSt =
13520 2 : UtilityRoutines::FindItemInList(ConstrNameSt,
13521 1 : state.dataConstruction->Construct,
13522 2 : state.dataHeatBal->TotConstructs); // Number of unshaded storm window construction that is created
13523 : // If necessary, create new material corresponding to the air layer between the storm winddow and the rest of the window
13524 1 : int MatNewStAir = createAirMaterialFromDistance(state, state.dataSurface->StormWindow(StormWinNum).StormWinDistance, "AIR:STORMWIN:");
13525 1 : if (ConstrNewSt == 0) {
13526 1 : ConstrNewSt = createConstructionWithStorm(
13527 1 : state, ConstrNum, ConstrNameSt, state.dataSurface->StormWindow(StormWinNum).StormWinMaterialNum, MatNewStAir);
13528 : }
13529 1 : state.dataSurface->SurfWinStormWinConstr(SurfNum) = ConstrNewSt;
13530 :
13531 : // create shaded constructions with storm window
13532 2 : state.dataSurface->Surface(SurfNum).shadedStormWinConstructionList.resize(
13533 1 : state.dataSurface->Surface(SurfNum).shadedConstructionList.size(),
13534 : 0); // make the shaded storm window size the same size as the number of shaded constructions
13535 1 : for (std::size_t iConstruction = 0; iConstruction < state.dataSurface->Surface(SurfNum).shadedConstructionList.size(); ++iConstruction) {
13536 0 : int curConstruction = state.dataSurface->Surface(SurfNum).shadedConstructionList[iConstruction];
13537 : // Set ShAndSt, which is true if the window has a shaded construction to which a storm window
13538 : // can be added. (A storm window can be added if there is an interior shade or blind and up to three
13539 : // glass layers, or there is a between-glass shade or blind and two glass layers.)
13540 0 : bool ShAndSt = false; // True if unshaded and shaded window can have a storm window
13541 0 : std::string ConstrNameSh = state.dataConstruction->Construct(curConstruction).Name; // Name of original shaded window construction
13542 0 : int TotLayers = state.dataConstruction->Construct(curConstruction).TotLayers; // Total layers in a construction
13543 0 : int MatIntSh = state.dataConstruction->Construct(curConstruction).LayerPoint(TotLayers); // Material number of interior shade or blind
13544 0 : int MatBetweenGlassSh = 0; // Material number of between-glass shade or blind
13545 0 : if (TotLayers == 5) MatBetweenGlassSh = state.dataConstruction->Construct(curConstruction).LayerPoint(3);
13546 0 : if (state.dataConstruction->Construct(curConstruction).TotGlassLayers <= 3 &&
13547 0 : (state.dataMaterial->Material(MatIntSh).Group == DataHeatBalance::MaterialGroup::Shade ||
13548 0 : state.dataMaterial->Material(MatIntSh).Group == DataHeatBalance::MaterialGroup::WindowBlind))
13549 0 : ShAndSt = true;
13550 0 : if (MatBetweenGlassSh > 0) {
13551 0 : if (state.dataMaterial->Material(MatBetweenGlassSh).Group == DataHeatBalance::MaterialGroup::Shade ||
13552 0 : state.dataMaterial->Material(MatBetweenGlassSh).Group == DataHeatBalance::MaterialGroup::WindowBlind) {
13553 0 : ShAndSt = true;
13554 : } else {
13555 0 : ShowContinueError(state,
13556 0 : "Window=" + state.dataSurface->Surface(SurfNum).Name +
13557 : " has a shaded construction to which a storm window cannot be applied.");
13558 0 : ShowContinueError(state, "Storm windows can only be applied to shaded constructions that:");
13559 0 : ShowContinueError(state, "have an interior shade or blind and up to three glass layers, or");
13560 0 : ShowContinueError(state, "have a between-glass shade or blind and two glass layers.");
13561 0 : ShowFatalError(state, "EnergyPlus is exiting due to reason stated above.");
13562 : }
13563 : }
13564 0 : if (ShAndSt) {
13565 0 : std::string ConstrNameStSh = "SHADEDCONSTRUCTIONWITHSTORMWIN:" + state.dataConstruction->Construct(iConstruction).Name + ":" +
13566 0 : ChrNum; // Name of shaded construction with storm window
13567 0 : int ConstrNewStSh = createConstructionWithStorm(
13568 0 : state, ConstrNum, ConstrNameStSh, state.dataSurface->StormWindow(StormWinNum).StormWinMaterialNum, MatNewStAir);
13569 0 : state.dataSurface->Surface(SurfNum).shadedStormWinConstructionList[iConstruction] =
13570 : ConstrNewStSh; // put in same index as the shaded constuction
13571 : }
13572 : } // end of loop for shaded constructions
13573 : } // end of loop over storm window objects
13574 1 : }
13575 :
13576 1 : int createAirMaterialFromDistance(EnergyPlusData &state, Real64 distance, std::string namePrefix)
13577 : {
13578 1 : int mmDistance = int(1000 * distance); // Thickness of air gap in mm (usually between storm window and rest of window)
13579 2 : std::string MatNameStAir = namePrefix + format("{}MM", mmDistance); // Name of created air layer material
13580 1 : int newAirMaterial = UtilityRoutines::FindItemInList(MatNameStAir, state.dataMaterial->Material, state.dataHeatBal->TotMaterials);
13581 1 : if (newAirMaterial == 0) {
13582 : // Create new material
13583 1 : state.dataHeatBal->TotMaterials = state.dataHeatBal->TotMaterials + 1;
13584 1 : newAirMaterial = state.dataHeatBal->TotMaterials;
13585 1 : state.dataMaterial->Material.redimension(state.dataHeatBal->TotMaterials);
13586 1 : state.dataHeatBal->NominalR.redimension(state.dataHeatBal->TotMaterials);
13587 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).Name = MatNameStAir;
13588 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).Group = DataHeatBalance::MaterialGroup::WindowGas;
13589 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).Roughness = DataSurfaces::SurfaceRoughness::MediumRough;
13590 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).Conductivity = 0.0;
13591 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).Density = 0.0;
13592 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).IsoMoistCap = 0.0;
13593 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).Porosity = 0.0;
13594 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).Resistance = 0.0;
13595 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).SpecHeat = 0.0;
13596 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).ThermGradCoef = 0.0;
13597 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).Thickness = distance;
13598 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).VaporDiffus = 0.0;
13599 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).GasType = 0;
13600 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).GasCon = 0.0;
13601 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).GasVis = 0.0;
13602 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).GasCp = 0.0;
13603 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).GasWght = 0.0;
13604 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).GasFract = 0.0;
13605 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).GasType(1) = 1;
13606 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).GlassSpectralDataPtr = 0;
13607 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).NumberOfGasesInMixture = 1;
13608 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).GasCon(1, 1) = 2.873e-3;
13609 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).GasCon(2, 1) = 7.760e-5;
13610 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).GasVis(1, 1) = 3.723e-6;
13611 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).GasVis(2, 1) = 4.940e-8;
13612 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).GasCp(1, 1) = 1002.737;
13613 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).GasCp(2, 1) = 1.2324e-2;
13614 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).GasWght(1) = 28.97;
13615 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).GasFract(1) = 1.0;
13616 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).AbsorpSolar = 0.0;
13617 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).AbsorpThermal = 0.0;
13618 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).AbsorpVisible = 0.0;
13619 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).Trans = 0.0;
13620 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).TransVis = 0.0;
13621 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).GlassTransDirtFactor = 0.0;
13622 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).ReflectShade = 0.0;
13623 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).ReflectShadeVis = 0.0;
13624 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).AbsorpThermalBack = 0.0;
13625 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).AbsorpThermalFront = 0.0;
13626 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).ReflectSolBeamBack = 0.0;
13627 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).ReflectSolBeamFront = 0.0;
13628 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).ReflectSolDiffBack = 0.0;
13629 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).ReflectSolDiffFront = 0.0;
13630 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).ReflectVisBeamBack = 0.0;
13631 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).ReflectVisBeamFront = 0.0;
13632 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).ReflectVisDiffBack = 0.0;
13633 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).ReflectVisDiffFront = 0.0;
13634 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).TransSolBeam = 0.0;
13635 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).TransThermal = 0.0;
13636 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).TransVisBeam = 0.0;
13637 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).BlindDataPtr = 0;
13638 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).WinShadeToGlassDist = 0.0;
13639 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).WinShadeTopOpeningMult = 0.0;
13640 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).WinShadeBottomOpeningMult = 0.0;
13641 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).WinShadeLeftOpeningMult = 0.0;
13642 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).WinShadeRightOpeningMult = 0.0;
13643 1 : state.dataMaterial->Material(state.dataHeatBal->TotMaterials).WinShadeAirFlowPermeability = 0.0;
13644 : }
13645 2 : return (newAirMaterial);
13646 : }
13647 :
13648 : // create a new construction with storm based on an old construction and storm and gap materials
13649 1 : int createConstructionWithStorm(EnergyPlusData &state, int oldConstruction, std::string name, int stormMaterial, int gapMaterial)
13650 : {
13651 : int newConstruct =
13652 2 : UtilityRoutines::FindItemInList(name,
13653 1 : state.dataConstruction->Construct,
13654 2 : state.dataHeatBal->TotConstructs); // Number of shaded storm window construction that is created
13655 1 : if (newConstruct == 0) {
13656 1 : state.dataHeatBal->TotConstructs = state.dataHeatBal->TotConstructs + 1;
13657 1 : newConstruct = state.dataHeatBal->TotConstructs;
13658 1 : state.dataConstruction->Construct.redimension(state.dataHeatBal->TotConstructs);
13659 1 : state.dataHeatBal->NominalRforNominalUCalculation.redimension(state.dataHeatBal->TotConstructs);
13660 1 : state.dataHeatBal->NominalU.redimension(state.dataHeatBal->TotConstructs);
13661 1 : state.dataHeatBal->NominalUBeforeAdjusted.redimension(state.dataHeatBal->TotConstructs);
13662 1 : state.dataHeatBal->CoeffAdjRatio.redimension(state.dataHeatBal->TotConstructs) = 1.0;
13663 :
13664 : // these Construct arrays dimensioned based on MaxSolidWinLayers
13665 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).setArraysBasedOnMaxSolidWinLayers(state);
13666 :
13667 1 : int TotLayersOld = state.dataConstruction->Construct(oldConstruction).TotLayers;
13668 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).LayerPoint({1, Construction::MaxLayersInConstruct}) = 0;
13669 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).LayerPoint(1) = stormMaterial;
13670 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).LayerPoint(2) = gapMaterial;
13671 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).LayerPoint({3, TotLayersOld + 2}) =
13672 2 : state.dataConstruction->Construct(oldConstruction).LayerPoint({1, TotLayersOld});
13673 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).Name = name;
13674 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).TotLayers = TotLayersOld + 2;
13675 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).TotSolidLayers =
13676 1 : state.dataConstruction->Construct(oldConstruction).TotSolidLayers + 1;
13677 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).TotGlassLayers =
13678 1 : state.dataConstruction->Construct(oldConstruction).TotGlassLayers + 1;
13679 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).TypeIsWindow = true;
13680 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).InsideAbsorpVis = 0.0;
13681 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).OutsideAbsorpVis = 0.0;
13682 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).InsideAbsorpSolar = 0.0;
13683 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).OutsideAbsorpSolar = 0.0;
13684 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).InsideAbsorpThermal =
13685 1 : state.dataConstruction->Construct(oldConstruction).InsideAbsorpThermal;
13686 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).OutsideAbsorpThermal =
13687 1 : state.dataMaterial->Material(stormMaterial).AbsorpThermalFront;
13688 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).OutsideRoughness = DataSurfaces::SurfaceRoughness::VerySmooth;
13689 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).DayltPropPtr = 0;
13690 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).CTFCross = 0.0;
13691 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).CTFFlux = 0.0;
13692 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).CTFInside = 0.0;
13693 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).CTFOutside = 0.0;
13694 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).CTFSourceIn = 0.0;
13695 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).CTFSourceOut = 0.0;
13696 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).CTFTimeStep = 0.0;
13697 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).CTFTSourceOut = 0.0;
13698 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).CTFTSourceIn = 0.0;
13699 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).CTFTSourceQ = 0.0;
13700 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).CTFTUserOut = 0.0;
13701 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).CTFTUserIn = 0.0;
13702 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).CTFTUserSource = 0.0;
13703 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).NumHistories = 0;
13704 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).NumCTFTerms = 0;
13705 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).UValue = 0.0;
13706 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).SourceSinkPresent = false;
13707 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).SolutionDimensions = 0;
13708 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).SourceAfterLayer = 0;
13709 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).TempAfterLayer = 0;
13710 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).ThicknessPerpend = 0.0;
13711 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).AbsDiffIn = 0.0;
13712 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).AbsDiffOut = 0.0;
13713 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).AbsDiff = 0.0;
13714 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).AbsDiffBack = 0.0;
13715 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).AbsDiffShade = 0.0;
13716 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).AbsDiffBackShade = 0.0;
13717 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).ShadeAbsorpThermal = 0.0;
13718 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).AbsBeamShadeCoef = 0.0;
13719 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).TransDiff = 0.0;
13720 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).TransDiffVis = 0.0;
13721 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).ReflectSolDiffBack = 0.0;
13722 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).ReflectSolDiffFront = 0.0;
13723 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).ReflectVisDiffBack = 0.0;
13724 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).ReflectVisDiffFront = 0.0;
13725 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).TransSolBeamCoef = 0.0;
13726 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).TransVisBeamCoef = 0.0;
13727 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).ReflSolBeamFrontCoef = 0.0;
13728 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).ReflSolBeamBackCoef = 0.0;
13729 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).W5FrameDivider = 0;
13730 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).FromWindow5DataFile = false;
13731 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).W5FileMullionWidth = 0.0;
13732 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).W5FileMullionOrientation =
13733 : DataWindowEquivalentLayer::Orientation::Invalid;
13734 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).W5FileGlazingSysWidth = 0.0;
13735 1 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).W5FileGlazingSysHeight = 0.0;
13736 8 : for (int Layer = 1; Layer <= state.dataHeatBal->MaxSolidWinLayers; ++Layer) {
13737 49 : for (int index = 1; index <= DataSurfaces::MaxPolyCoeff; ++index) {
13738 42 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).AbsBeamCoef(Layer)(index) = 0.0;
13739 42 : state.dataConstruction->Construct(state.dataHeatBal->TotConstructs).AbsBeamBackCoef(Layer)(index) = 0.0;
13740 : }
13741 : }
13742 : }
13743 1 : return (newConstruct);
13744 : }
13745 :
13746 8 : void ModifyWindow(EnergyPlusData &state,
13747 : int const SurfNum, // SurfNum has construction of glazing system from Window5 Data File;
13748 : bool &ErrorsFound, // Set to true if errors found
13749 : int &AddedSubSurfaces // Subsurfaces added when window references a
13750 : )
13751 : {
13752 :
13753 : // SUBROUTINE INFORMATION:
13754 : // AUTHOR Fred Winkelmann
13755 : // DATE WRITTEN Feb 2002
13756 : // MODIFIED June 2004, FCW: SinAzim, CosAzim, SinTilt, CosTilt, OutNormVec, GrossArea
13757 : // and Perimeter weren't being set for created window for case when
13758 : // window from Window5DataFile had two different glazing systems. Also,
13759 : // GrossArea and Perimeter of original window were not being recalculated.
13760 : // October 2007, LKL: Net area for shading calculations was not being
13761 : // recalculated.
13762 : // RE-ENGINEERED na
13763 :
13764 : // PURPOSE OF THIS SUBROUTINE:
13765 : // If a window from the Window5DataFile has one glazing system, modify the
13766 : // vertex coordinates of the original window to correspond to the dimensions
13767 : // of the glazing system on the Data File.
13768 : // If a window from the Window5DataFile has two different glazing systems, split
13769 : // the window into two separate windows with different properties and adjust the
13770 : // vertices of these windows taking into account the dimensions of the glazing systems
13771 : // on the Data File and the width and orientation of the mullion that separates
13772 : // the glazing systems.
13773 :
13774 : // Using/Aliasing
13775 :
13776 : using namespace Vectors;
13777 :
13778 : // Locals
13779 : // SUBROUTINE ARGUMENT DEFINITIONS:
13780 : // If there is a second glazing systme on the Data File, SurfNum+1
13781 : // has the construction of the second glazing system.
13782 :
13783 : // 2-glazing system Window5 data file entry
13784 :
13785 : // DERIVED TYPE DEFINITIONS:
13786 :
13787 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
13788 : Real64 H; // Height and width of original window (m)
13789 : Real64 W;
13790 : // unused1208 REAL(r64) :: MulWidth ! Mullion width (m)
13791 : Real64 h1; // height and width of first glazing system (m)
13792 : Real64 w1;
13793 : // unused1208 REAL(r64) :: h2,w2 ! height and width of second glazing system (m)
13794 : // unused1208 type (rectangularwindow) :: NewCoord
13795 : int IConst; // Construction number of first glazing system
13796 : int IConst2; // Construction number of second glazing system
13797 16 : std::string Const2Name; // Name of construction of second glazing system
13798 : // unused1208 REAL(r64) :: AreaNew ! Sum of areas of the two glazing systems (m2)
13799 :
13800 8 : struct rectangularwindow
13801 : {
13802 : // Members
13803 : Array1D<Vector> Vertex;
13804 :
13805 : // Default Constructor
13806 8 : rectangularwindow() : Vertex(4)
13807 : {
13808 8 : }
13809 : };
13810 :
13811 : // Object Data
13812 16 : Vector TVect;
13813 16 : rectangularwindow OriginalCoord;
13814 :
13815 8 : IConst = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction;
13816 :
13817 : // Height and width of original window
13818 8 : TVect = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(3) - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(2);
13819 8 : W = VecLength(TVect); // SQRT((X(3)-X(2))**2 + (Y(3)-Y(2))**2 + (Z(3)-Z(2))**2)
13820 8 : TVect = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(2) - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(1);
13821 8 : H = VecLength(TVect); // SQRT((X(1)-X(2))**2 + (Y(1)-Y(2))**2 + (Z(1)-Z(2))**2)
13822 :
13823 : // Save coordinates of original window in case Window 5 data overwrites.
13824 8 : OriginalCoord.Vertex({1, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides}) =
13825 16 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex({1, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides});
13826 :
13827 : // Height and width of first glazing system
13828 8 : h1 = state.dataConstruction->Construct(IConst).W5FileGlazingSysHeight;
13829 8 : w1 = state.dataConstruction->Construct(IConst).W5FileGlazingSysWidth;
13830 :
13831 8 : Const2Name = state.dataConstruction->Construct(IConst).Name + ":2";
13832 8 : IConst2 = UtilityRoutines::FindItemInList(Const2Name, state.dataConstruction->Construct);
13833 :
13834 8 : if (IConst2 == 0) { // Only one glazing system on Window5 Data File for this window.
13835 :
13836 : // So... original dimensions and area of window are used (entered in IDF)
13837 : // Warning if dimensions of original window differ from those on Data File by more than 10%
13838 :
13839 8 : if (std::abs((H - h1) / H) > 0.10 || std::abs((W - w1) / W) > 0.10) {
13840 :
13841 8 : if (state.dataGlobal->DisplayExtraWarnings) {
13842 0 : ShowWarningError(state,
13843 0 : "SurfaceGeometry: ModifyWindow: Window " + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
13844 0 : " uses the Window5 Data File Construction " + state.dataConstruction->Construct(IConst).Name);
13845 0 : ShowContinueError(state, format("The height {:.3R}(m) or width (m) of this window differs by more than 10%{:.3R}", H, W));
13846 0 : ShowContinueError(state,
13847 0 : format("from the corresponding height {:.3R} (m) or width (m) on the Window5 Data file.{:.3R}", h1, w1));
13848 0 : ShowContinueError(state, "This will affect the frame heat transfer calculation if the frame in the Data File entry");
13849 0 : ShowContinueError(state, "is not uniform, i.e., has sections with different geometry and/or thermal properties.");
13850 : } else {
13851 8 : ++state.dataSurfaceGeometry->Warning1Count;
13852 : }
13853 : }
13854 :
13855 : // Calculate net area for base surface
13856 8 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).Area -=
13857 8 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area;
13858 8 : if (state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).Area <= 0.0) {
13859 0 : ShowSevereError(state,
13860 0 : "Subsurfaces have too much area for base surface=" +
13861 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).Name);
13862 0 : ShowContinueError(state, "Subsurface creating error=" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name);
13863 0 : ErrorsFound = true;
13864 : }
13865 :
13866 : // Net area of base surface with unity window multipliers (used in shadowing checks)
13867 8 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).NetAreaShadowCalc -=
13868 8 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area / state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier;
13869 :
13870 : } else { // Two glazing systems on Window5 data file for this window
13871 :
13872 : // if exterior window, okay.
13873 :
13874 0 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == ExternalEnvironment) {
13875 : // There are two glazing systems (separated by a vertical or horizontal mullion) on the Window5 Data File.
13876 : // Fill in geometry data for the second window (corresponding to the second glazing system on the data file.
13877 : // The first glazing system is assumed to be at left for vertical mullion, at bottom for horizontal mullion.
13878 : // The second glazing system is assumed to be at right for vertical mullion, at top for horizontal mullion.
13879 : // The lower left-hand corner of the original window (its vertex #2) is assumed to coincide with
13880 : // vertex #2 of the first glazing system.
13881 :
13882 0 : if (state.dataGlobal->DisplayExtraWarnings) {
13883 0 : ShowMessage(state,
13884 0 : "SurfaceGeometry: ModifyWindow: Window " + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
13885 0 : " has been replaced with the Window 5/6 two glazing system=\"" + state.dataConstruction->Construct(IConst).Name +
13886 : "\".");
13887 0 : ShowContinueError(state, "Note that originally entered dimensions are overridden.");
13888 : } else {
13889 0 : ++state.dataSurfaceGeometry->Warning2Count;
13890 : }
13891 :
13892 : // Allocate another window
13893 0 : AddWindow(state, SurfNum, ErrorsFound, AddedSubSurfaces);
13894 :
13895 0 : } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond > 0) { // Interior window, specified ! not external environment
13896 :
13897 0 : if (state.dataGlobal->DisplayExtraWarnings) {
13898 0 : ShowWarningError(state,
13899 0 : "SurfaceGeometry: ModifyWindow: Interior Window " + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
13900 0 : " has been replaced with the Window 5/6 two glazing system=\"" +
13901 0 : state.dataConstruction->Construct(IConst).Name + "\".");
13902 0 : ShowContinueError(
13903 : state, "Please check to make sure interior window is correct. Note that originally entered dimensions are overridden.");
13904 : } else {
13905 0 : ++state.dataSurfaceGeometry->Warning3Count;
13906 : }
13907 :
13908 0 : AddWindow(state, SurfNum, ErrorsFound, AddedSubSurfaces);
13909 :
13910 : } else { // Interior window, specified not entered
13911 :
13912 0 : ShowSevereError(state,
13913 0 : "SurfaceGeometry: ModifyWindow: Interior Window " + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name +
13914 : " is a window in an adjacent zone.");
13915 0 : ShowContinueError(
13916 0 : state, "Attempted to add/reverse Window 5/6 multiple glazing system=\"" + state.dataConstruction->Construct(IConst).Name + "\".");
13917 0 : ShowContinueError(state, "Cannot use these Window 5/6 constructs for these Interior Windows. Program will terminate.");
13918 0 : ErrorsFound = true;
13919 : }
13920 :
13921 : } // End of check if one or two glazing systems are on the Window5 Data File
13922 8 : }
13923 :
13924 0 : void AddWindow(EnergyPlusData &state,
13925 : int const SurfNum, // SurfNum has construction of glazing system from Window5 Data File;
13926 : bool &ErrorsFound, // Set to true if errors found
13927 : int &AddedSubSurfaces // Subsurfaces added when window references a
13928 : )
13929 : {
13930 :
13931 : // SUBROUTINE INFORMATION:
13932 : // AUTHOR Linda Lawrie
13933 : // DATE WRITTEN Nov 2008
13934 : // MODIFIED na
13935 : // RE-ENGINEERED na
13936 :
13937 : // PURPOSE OF THIS SUBROUTINE:
13938 : // This routine is called from ModifyWindow to add a window. Allows it to be
13939 : // called in more than one place in the calling routine so as to be able to have
13940 : // specific warnings or errors issued.
13941 :
13942 : // Using/Aliasing
13943 :
13944 : using namespace Vectors;
13945 :
13946 : // Locals
13947 : // SUBROUTINE ARGUMENT DEFINITIONS:
13948 : // If there is a second glazing systme on the Data File, SurfNum+1
13949 : // has the construction of the second glazing system.
13950 :
13951 : // 2-glazing system Window5 data file entry
13952 :
13953 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
13954 : int loop; // DO loop index
13955 : Real64 H; // Height and width of original window (m)
13956 : Real64 W;
13957 : Real64 MulWidth; // Mullion width (m)
13958 : Real64 h1; // height and width of first glazing system (m)
13959 : Real64 w1;
13960 : Real64 h2; // height and width of second glazing system (m)
13961 : Real64 w2;
13962 : Real64 xa; // Vertex intermediate variables (m)
13963 : Real64 ya;
13964 : Real64 za;
13965 : Real64 xb;
13966 : Real64 yb;
13967 : Real64 zb;
13968 : Real64 dx; // Vertex displacements from original window (m)
13969 : Real64 dy;
13970 : int IConst; // Construction number of first glazing system
13971 : int IConst2; // Construction number of second glazing system
13972 0 : std::string Const2Name; // Name of construction of second glazing system
13973 : Real64 AreaNew; // Sum of areas of the two glazing systems (m2)
13974 :
13975 0 : struct rectangularwindow
13976 : {
13977 : // Members
13978 : Array1D<Vector> Vertex;
13979 :
13980 : // Default Constructor
13981 0 : rectangularwindow() : Vertex(4)
13982 : {
13983 0 : }
13984 : };
13985 :
13986 : // Object Data
13987 0 : Vector TVect;
13988 0 : rectangularwindow NewCoord;
13989 0 : rectangularwindow OriginalCoord;
13990 :
13991 0 : IConst = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction;
13992 :
13993 : // Height and width of original window
13994 0 : TVect = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(3) - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(2);
13995 0 : W = VecLength(TVect); // SQRT((X(3)-X(2))**2 + (Y(3)-Y(2))**2 + (Z(3)-Z(2))**2)
13996 0 : TVect = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(2) - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(1);
13997 0 : H = VecLength(TVect); // SQRT((X(1)-X(2))**2 + (Y(1)-Y(2))**2 + (Z(1)-Z(2))**2)
13998 :
13999 : // Save coordinates of original window in case Window 5 data overwrites.
14000 0 : OriginalCoord.Vertex({1, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides}) =
14001 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex({1, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides});
14002 :
14003 : // Height and width of first glazing system
14004 0 : h1 = state.dataConstruction->Construct(IConst).W5FileGlazingSysHeight;
14005 0 : w1 = state.dataConstruction->Construct(IConst).W5FileGlazingSysWidth;
14006 :
14007 0 : Const2Name = state.dataConstruction->Construct(IConst).Name + ":2";
14008 0 : IConst2 = UtilityRoutines::FindItemInList(Const2Name, state.dataConstruction->Construct);
14009 :
14010 0 : ++AddedSubSurfaces;
14011 0 : state.dataSurfaceGeometry->SurfaceTmp.redimension(++state.dataSurface->TotSurfaces);
14012 :
14013 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Vertex.allocate(4);
14014 :
14015 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Name = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name + ":2";
14016 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Construction = IConst2;
14017 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).ConstructionStoredInputValue = IConst2;
14018 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Class = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class;
14019 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Azimuth = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Azimuth;
14020 : // Sine and cosine of azimuth and tilt
14021 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).SinAzim = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinAzim;
14022 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).CosAzim = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosAzim;
14023 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).SinTilt = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SinTilt;
14024 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).CosTilt = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).CosTilt;
14025 : // Outward normal unit vector (pointing away from room)
14026 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Centroid = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Centroid;
14027 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).lcsx = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsx;
14028 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).lcsy = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsy;
14029 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).lcsz = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).lcsz;
14030 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).NewellAreaVector =
14031 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NewellAreaVector;
14032 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).OutNormVec = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OutNormVec;
14033 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Reveal = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Reveal;
14034 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Shape = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Shape;
14035 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Sides = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides;
14036 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Tilt = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt;
14037 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).ConvOrientation =
14038 0 : ConvectionCoefficients::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Tilt);
14039 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).HeatTransSurf =
14040 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf;
14041 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).BaseSurfName =
14042 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName;
14043 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).BaseSurf = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf;
14044 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).ZoneName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName;
14045 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Zone = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone;
14046 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).ExtBoundCondName =
14047 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName;
14048 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).ExtBoundCond =
14049 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond;
14050 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).ExtSolar = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtSolar;
14051 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).ExtWind = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtWind;
14052 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).ViewFactorGround =
14053 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGround;
14054 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).ViewFactorSky =
14055 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSky;
14056 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).ViewFactorGroundIR =
14057 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorGroundIR;
14058 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).ViewFactorSkyIR =
14059 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ViewFactorSkyIR;
14060 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).OSCPtr = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).OSCPtr;
14061 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).SchedShadowSurfIndex =
14062 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).SchedShadowSurfIndex;
14063 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).activeWindowShadingControl =
14064 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeWindowShadingControl;
14065 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).windowShadingControlList =
14066 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).windowShadingControlList;
14067 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).HasShadeControl =
14068 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HasShadeControl;
14069 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).activeShadedConstruction =
14070 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).activeShadedConstruction;
14071 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).windowShadingControlList =
14072 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).windowShadingControlList;
14073 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).shadedStormWinConstructionList =
14074 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).shadedStormWinConstructionList;
14075 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).FrameDivider =
14076 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).FrameDivider;
14077 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Multiplier = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier;
14078 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).NetAreaShadowCalc =
14079 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NetAreaShadowCalc;
14080 :
14081 0 : MulWidth = state.dataConstruction->Construct(IConst).W5FileMullionWidth;
14082 0 : w2 = state.dataConstruction->Construct(IConst2).W5FileGlazingSysWidth;
14083 0 : h2 = state.dataConstruction->Construct(IConst2).W5FileGlazingSysHeight;
14084 :
14085 : // Correction to net area of base surface. Add back in the original glazing area and subtract the
14086 : // area of the two glazing systems. Note that for Surface(SurfNum)%Class = 'Window' the effect
14087 : // of a window multiplier is included in the glazing area. Note that frame areas are subtracted later.
14088 :
14089 0 : AreaNew = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier * (h1 * w1 + h2 * w2); // both glazing systems
14090 : // Adjust net area for base surface
14091 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).Area -= AreaNew;
14092 :
14093 : // Net area of base surface with unity window multipliers (used in shadowing checks)
14094 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).NetAreaShadowCalc -=
14095 0 : AreaNew / state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier;
14096 :
14097 : // Reset area, etc. of original window
14098 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Multiplier * (h1 * w1);
14099 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).GrossArea = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Area;
14100 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).NetAreaShadowCalc = h1 * w1;
14101 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Perimeter = 2 * (h1 + w1);
14102 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Height = h1;
14103 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Width = w1;
14104 : // Set area, etc. of new window
14105 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Area =
14106 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Multiplier * (h2 * w2);
14107 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).GrossArea =
14108 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Area;
14109 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).NetAreaShadowCalc = h2 * w2;
14110 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Perimeter = 2 * (h2 + w2);
14111 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Height = h2;
14112 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Width = w2;
14113 :
14114 0 : if (state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).Area <= 0.0) {
14115 0 : ShowSevereError(state,
14116 0 : "SurfaceGeometry: ModifyWindow: Subsurfaces have too much area for base surface=" +
14117 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf).Name);
14118 0 : ShowContinueError(state, "Subsurface (window) creating error=" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name);
14119 0 : ShowContinueError(state,
14120 0 : format("This window has been replaced by two windows from the Window5 Data File of total area {:.2R} m2", AreaNew));
14121 0 : ErrorsFound = true;
14122 : }
14123 :
14124 : // Assign vertices to the new window; modify vertices of original window.
14125 : // In the following, vertices are numbered counter-clockwise with vertex #1 at the upper left.
14126 :
14127 0 : if (state.dataConstruction->Construct(IConst).W5FileMullionOrientation == DataWindowEquivalentLayer::Orientation::Vertical) {
14128 :
14129 : // VERTICAL MULLION: original window is modified to become left-hand glazing (system #1);
14130 : // new window is created to become right-hand glazing (system #2)
14131 :
14132 : // Left-hand glazing
14133 :
14134 : // Vertex 1
14135 0 : dx = 0.0;
14136 0 : dy = H - h1;
14137 0 : xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
14138 0 : ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
14139 0 : za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
14140 0 : xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
14141 0 : yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
14142 0 : zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
14143 0 : NewCoord.Vertex(1).x = xa + (dx / W) * (xb - xa);
14144 0 : NewCoord.Vertex(1).y = ya + (dx / W) * (yb - ya);
14145 0 : NewCoord.Vertex(1).z = za + (dx / W) * (zb - za);
14146 :
14147 : // Vertex 2
14148 0 : dx = 0.0;
14149 0 : dy = H;
14150 0 : xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
14151 0 : ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
14152 0 : za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
14153 0 : xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
14154 0 : yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
14155 0 : zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
14156 0 : NewCoord.Vertex(2).x = xa + (dx / W) * (xb - xa);
14157 0 : NewCoord.Vertex(2).y = ya + (dx / W) * (yb - ya);
14158 0 : NewCoord.Vertex(2).z = za + (dx / W) * (zb - za);
14159 :
14160 : // Vertex 3
14161 0 : dx = w1;
14162 0 : dy = H;
14163 0 : xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
14164 0 : ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
14165 0 : za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
14166 0 : xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
14167 0 : yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
14168 0 : zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
14169 0 : NewCoord.Vertex(3).x = xa + (dx / W) * (xb - xa);
14170 0 : NewCoord.Vertex(3).y = ya + (dx / W) * (yb - ya);
14171 0 : NewCoord.Vertex(3).z = za + (dx / W) * (zb - za);
14172 :
14173 : // Vertex 4
14174 0 : dx = w1;
14175 0 : dy = H - h1;
14176 0 : xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
14177 0 : ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
14178 0 : za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
14179 0 : xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
14180 0 : yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
14181 0 : zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
14182 0 : NewCoord.Vertex(4).x = xa + (dx / W) * (xb - xa);
14183 0 : NewCoord.Vertex(4).y = ya + (dx / W) * (yb - ya);
14184 0 : NewCoord.Vertex(4).z = za + (dx / W) * (zb - za);
14185 :
14186 0 : for (loop = 1; loop <= state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides; ++loop) {
14187 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(loop) = NewCoord.Vertex(loop);
14188 : }
14189 :
14190 : // Right-hand glazing
14191 :
14192 : // Vertex 1
14193 0 : dx = w1 + MulWidth;
14194 0 : dy = H - (h1 + h2) / 2.0;
14195 0 : xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
14196 0 : ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
14197 0 : za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
14198 0 : xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
14199 0 : yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
14200 0 : zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
14201 0 : NewCoord.Vertex(1).x = xa + (dx / W) * (xb - xa);
14202 0 : NewCoord.Vertex(1).y = ya + (dx / W) * (yb - ya);
14203 0 : NewCoord.Vertex(1).z = za + (dx / W) * (zb - za);
14204 :
14205 : // Vertex 2
14206 0 : dx = w1 + MulWidth;
14207 0 : dy = H + (h2 - h1) / 2.0;
14208 0 : xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
14209 0 : ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
14210 0 : za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
14211 0 : xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
14212 0 : yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
14213 0 : zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
14214 0 : NewCoord.Vertex(2).x = xa + (dx / W) * (xb - xa);
14215 0 : NewCoord.Vertex(2).y = ya + (dx / W) * (yb - ya);
14216 0 : NewCoord.Vertex(2).z = za + (dx / W) * (zb - za);
14217 :
14218 : // Vertex 3
14219 0 : dx = w1 + MulWidth + w2;
14220 0 : dy = H + (h2 - h1) / 2.0;
14221 0 : xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
14222 0 : ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
14223 0 : za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
14224 0 : xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
14225 0 : yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
14226 0 : zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
14227 0 : NewCoord.Vertex(3).x = xa + (dx / W) * (xb - xa);
14228 0 : NewCoord.Vertex(3).y = ya + (dx / W) * (yb - ya);
14229 0 : NewCoord.Vertex(3).z = za + (dx / W) * (zb - za);
14230 :
14231 : // Vertex 4
14232 0 : dx = w1 + MulWidth + w2;
14233 0 : dy = H - (h1 + h2) / 2.0;
14234 0 : xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
14235 0 : ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
14236 0 : za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
14237 0 : xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
14238 0 : yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
14239 0 : zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
14240 0 : NewCoord.Vertex(4).x = xa + (dx / W) * (xb - xa);
14241 0 : NewCoord.Vertex(4).y = ya + (dx / W) * (yb - ya);
14242 0 : NewCoord.Vertex(4).z = za + (dx / W) * (zb - za);
14243 :
14244 0 : for (loop = 1; loop <= state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Sides; ++loop) {
14245 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Vertex(loop) = NewCoord.Vertex(loop);
14246 : }
14247 :
14248 : } else { // Horizontal mullion
14249 :
14250 : // HORIZONTAL MULLION: original window is modified to become bottom glazing (system #1);
14251 : // new window is created to become top glazing (system #2)
14252 :
14253 : // Bottom glazing
14254 :
14255 : // Vertex 1
14256 0 : dx = 0.0;
14257 0 : dy = H - h1;
14258 0 : xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
14259 0 : ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
14260 0 : za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
14261 0 : xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
14262 0 : yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
14263 0 : zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
14264 0 : NewCoord.Vertex(1).x = xa + (dx / W) * (xb - xa);
14265 0 : NewCoord.Vertex(1).y = ya + (dx / W) * (yb - ya);
14266 0 : NewCoord.Vertex(1).z = za + (dx / W) * (zb - za);
14267 :
14268 : // Vertex 2
14269 0 : dx = 0.0;
14270 0 : dy = H;
14271 0 : xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
14272 0 : ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
14273 0 : za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
14274 0 : xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
14275 0 : yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
14276 0 : zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
14277 0 : NewCoord.Vertex(2).x = xa + (dx / W) * (xb - xa);
14278 0 : NewCoord.Vertex(2).y = ya + (dx / W) * (yb - ya);
14279 0 : NewCoord.Vertex(2).z = za + (dx / W) * (zb - za);
14280 :
14281 : // Vertex 3
14282 0 : dx = w1;
14283 0 : dy = H;
14284 0 : xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
14285 0 : ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
14286 0 : za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
14287 0 : xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
14288 0 : yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
14289 0 : zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
14290 0 : NewCoord.Vertex(3).x = xa + (dx / W) * (xb - xa);
14291 0 : NewCoord.Vertex(3).y = ya + (dx / W) * (yb - ya);
14292 0 : NewCoord.Vertex(3).z = za + (dx / W) * (zb - za);
14293 :
14294 : // Vertex 4
14295 0 : dx = w1;
14296 0 : dy = H - h1;
14297 0 : xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
14298 0 : ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
14299 0 : za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
14300 0 : xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
14301 0 : yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
14302 0 : zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
14303 0 : NewCoord.Vertex(4).x = xa + (dx / W) * (xb - xa);
14304 0 : NewCoord.Vertex(4).y = ya + (dx / W) * (yb - ya);
14305 0 : NewCoord.Vertex(4).z = za + (dx / W) * (zb - za);
14306 :
14307 0 : for (loop = 1; loop <= state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides; ++loop) {
14308 0 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(loop) = NewCoord.Vertex(loop);
14309 : }
14310 :
14311 : // Top glazing
14312 :
14313 : // Vertex 1
14314 0 : dx = (w1 - w2) / 2.0;
14315 0 : dy = H - (h1 + h2 + MulWidth);
14316 0 : xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
14317 0 : ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
14318 0 : za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
14319 0 : xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
14320 0 : yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
14321 0 : zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
14322 0 : NewCoord.Vertex(1).x = xa + (dx / W) * (xb - xa);
14323 0 : NewCoord.Vertex(1).y = ya + (dx / W) * (yb - ya);
14324 0 : NewCoord.Vertex(1).z = za + (dx / W) * (zb - za);
14325 :
14326 : // Vertex 2
14327 0 : dx = (w1 - w2) / 2.0;
14328 0 : dy = H - (h1 + MulWidth);
14329 0 : xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
14330 0 : ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
14331 0 : za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
14332 0 : xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
14333 0 : yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
14334 0 : zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
14335 0 : NewCoord.Vertex(2).x = xa + (dx / W) * (xb - xa);
14336 0 : NewCoord.Vertex(2).y = ya + (dx / W) * (yb - ya);
14337 0 : NewCoord.Vertex(2).z = za + (dx / W) * (zb - za);
14338 :
14339 : // Vertex 3
14340 0 : dx = (w1 + w2) / 2.0;
14341 0 : dy = H - (h1 + MulWidth);
14342 0 : xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
14343 0 : ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
14344 0 : za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
14345 0 : xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
14346 0 : yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
14347 0 : zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
14348 0 : NewCoord.Vertex(3).x = xa + (dx / W) * (xb - xa);
14349 0 : NewCoord.Vertex(3).y = ya + (dx / W) * (yb - ya);
14350 0 : NewCoord.Vertex(3).z = za + (dx / W) * (zb - za);
14351 :
14352 : // Vertex 4
14353 0 : dx = (w1 + w2) / 2.0;
14354 0 : dy = H - (h1 + h2 + MulWidth);
14355 0 : xa = OriginalCoord.Vertex(1).x + (dy / H) * (OriginalCoord.Vertex(2).x - OriginalCoord.Vertex(1).x);
14356 0 : ya = OriginalCoord.Vertex(1).y + (dy / H) * (OriginalCoord.Vertex(2).y - OriginalCoord.Vertex(1).y);
14357 0 : za = OriginalCoord.Vertex(1).z + (dy / H) * (OriginalCoord.Vertex(2).z - OriginalCoord.Vertex(1).z);
14358 0 : xb = OriginalCoord.Vertex(4).x + (dy / H) * (OriginalCoord.Vertex(3).x - OriginalCoord.Vertex(4).x);
14359 0 : yb = OriginalCoord.Vertex(4).y + (dy / H) * (OriginalCoord.Vertex(3).y - OriginalCoord.Vertex(4).y);
14360 0 : zb = OriginalCoord.Vertex(4).z + (dy / H) * (OriginalCoord.Vertex(3).z - OriginalCoord.Vertex(4).z);
14361 0 : NewCoord.Vertex(4).x = xa + (dx / W) * (xb - xa);
14362 0 : NewCoord.Vertex(4).y = ya + (dx / W) * (yb - ya);
14363 0 : NewCoord.Vertex(4).z = za + (dx / W) * (zb - za);
14364 :
14365 0 : for (loop = 1; loop <= state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Sides; ++loop) {
14366 0 : state.dataSurfaceGeometry->SurfaceTmp(state.dataSurface->TotSurfaces).Vertex(loop) = NewCoord.Vertex(loop);
14367 : }
14368 :
14369 : } // End of check if vertical or horizontal mullion
14370 0 : }
14371 :
14372 40339 : void TransformVertsByAspect(EnergyPlusData &state,
14373 : int const SurfNum, // Current surface number
14374 : int const NSides // Number of sides to figure
14375 : )
14376 : {
14377 : // SUBROUTINE INFORMATION:
14378 : // AUTHOR Brent T Griffith
14379 : // DATE WRITTEN April 2003
14380 : // MODIFIED na
14381 : // RE-ENGINEERED na
14382 :
14383 : // PURPOSE OF THIS SUBROUTINE:
14384 : // Alter input for surface geometry
14385 : // Optimizing building design for energy can involve
14386 : // altering building geometry. Rather than assemble routines to transform
14387 : // geometry through pre-processing on input, it may be simpler to change
14388 : // vertices within EnergyPlus since it already reads the data from the input
14389 : // file and there would no longer be a need to rewrite the text data.
14390 : // This is essentially a crude hack to allow adjusting geometry with
14391 : // a single parameter...
14392 :
14393 : // METHODOLOGY EMPLOYED:
14394 : // once vertices have been converted to WCS, change them to reflect a different aspect
14395 : // ratio for the entire building based on user input.
14396 : // This routine is called once for each surface by subroutine GetVertices
14397 :
14398 40339 : static std::string const CurrentModuleObject("GeometryTransform");
14399 :
14400 40387 : Array1D_string cAlphas(1);
14401 40387 : Array1D<Real64> rNumerics(2);
14402 : int NAlphas;
14403 : int NNum;
14404 : int IOStat;
14405 40339 : auto &OldAspectRatio = state.dataSurfaceGeometry->OldAspectRatio;
14406 40339 : auto &NewAspectRatio = state.dataSurfaceGeometry->NewAspectRatio;
14407 40339 : auto &transformPlane = state.dataSurfaceGeometry->transformPlane;
14408 : int n;
14409 : Real64 Xo;
14410 : Real64 XnoRot;
14411 : Real64 Xtrans;
14412 : Real64 Yo;
14413 : Real64 YnoRot;
14414 : Real64 Ytrans;
14415 : // begin execution
14416 : // get user input...
14417 :
14418 40339 : if (state.dataSurfaceGeometry->firstTime) {
14419 742 : if (state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject) == 1) {
14420 5 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
14421 : CurrentModuleObject,
14422 : 1,
14423 : cAlphas,
14424 : NAlphas,
14425 : rNumerics,
14426 : NNum,
14427 : IOStat,
14428 1 : state.dataIPShortCut->lNumericFieldBlanks,
14429 1 : state.dataIPShortCut->lAlphaFieldBlanks,
14430 1 : state.dataIPShortCut->cAlphaFieldNames,
14431 1 : state.dataIPShortCut->cNumericFieldNames);
14432 1 : OldAspectRatio = rNumerics(1);
14433 1 : NewAspectRatio = rNumerics(2);
14434 1 : transformPlane = cAlphas(1);
14435 1 : if (transformPlane != "XY") {
14436 0 : ShowWarningError(
14437 0 : state, CurrentModuleObject + ": invalid " + state.dataIPShortCut->cAlphaFieldNames(1) + "=\"" + cAlphas(1) + "...ignored.");
14438 : }
14439 1 : state.dataSurfaceGeometry->firstTime = false;
14440 1 : state.dataSurfaceGeometry->noTransform = false;
14441 1 : state.dataSurface->AspectTransform = true;
14442 1 : if (state.dataSurface->WorldCoordSystem) {
14443 0 : ShowWarningError(state, CurrentModuleObject + ": must use Relative Coordinate System. Transform request ignored.");
14444 0 : state.dataSurfaceGeometry->noTransform = true;
14445 0 : state.dataSurface->AspectTransform = false;
14446 : }
14447 : } else {
14448 741 : state.dataSurfaceGeometry->firstTime = false;
14449 : }
14450 : }
14451 40339 : if (state.dataSurfaceGeometry->noTransform) return;
14452 :
14453 : // check surface type.
14454 48 : if (!state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf) {
14455 : // Site Shading do not get transformed.
14456 2 : if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Detached_F) return;
14457 : }
14458 :
14459 : // testing method of transforming x and y coordinates as follows
14460 :
14461 : // this works if not rotated wrt north axis ... but if it is, then trouble
14462 : // try to first derotate it , transform by aspect and then rotate back.
14463 :
14464 240 : for (n = 1; n <= NSides; ++n) {
14465 192 : Xo = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x; // world coordinates.... shifted by relative north angle...
14466 192 : Yo = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y;
14467 : // next derotate the building
14468 192 : XnoRot = Xo * state.dataSurfaceGeometry->CosBldgRelNorth + Yo * state.dataSurfaceGeometry->SinBldgRelNorth;
14469 192 : YnoRot = Yo * state.dataSurfaceGeometry->CosBldgRelNorth - Xo * state.dataSurfaceGeometry->SinBldgRelNorth;
14470 : // translate
14471 192 : Xtrans = XnoRot * std::sqrt(NewAspectRatio / OldAspectRatio);
14472 192 : Ytrans = YnoRot * std::sqrt(OldAspectRatio / NewAspectRatio);
14473 : // rerotate
14474 192 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).x =
14475 192 : Xtrans * state.dataSurfaceGeometry->CosBldgRelNorth - Ytrans * state.dataSurfaceGeometry->SinBldgRelNorth;
14476 :
14477 192 : state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(n).y =
14478 192 : Xtrans * state.dataSurfaceGeometry->SinBldgRelNorth + Ytrans * state.dataSurfaceGeometry->CosBldgRelNorth;
14479 : }
14480 : }
14481 :
14482 771 : void CalcSurfaceCentroid(EnergyPlusData &state)
14483 : {
14484 :
14485 : // SUBROUTINE INFORMATION:
14486 : // AUTHOR B. Griffith
14487 : // DATE WRITTEN Feb. 2004
14488 : // MODIFIED na
14489 : // RE-ENGINEERED na
14490 :
14491 : // PURPOSE OF THIS SUBROUTINE:
14492 : // compute centroid of all the surfaces in the main
14493 : // surface structure. Store the vertex coordinates of
14494 : // the centroid in the 'SURFACE' derived type.
14495 :
14496 : // METHODOLOGY EMPLOYED:
14497 : // The centroid of triangle is easily computed by averaging the vertices
14498 : // The centroid of a quadrilateral is computed by area weighting the centroids
14499 : // of two triangles.
14500 : // (Algorithm would need to be changed for higher order
14501 : // polygons with more than four sides).
14502 :
14503 : using namespace Vectors;
14504 :
14505 771 : auto &Triangle1 = state.dataSurfaceGeometry->Triangle1;
14506 771 : auto &Triangle2 = state.dataSurfaceGeometry->Triangle2;
14507 771 : static Vector const zero_vector(0.0);
14508 1542 : Vector centroid;
14509 :
14510 771 : int negZcount(0); // for warning error in surface centroids
14511 :
14512 : // loop through all the surfaces
14513 44533 : for (int ThisSurf = 1; ThisSurf <= state.dataSurface->TotSurfaces; ++ThisSurf) {
14514 43762 : auto &surface(state.dataSurface->Surface(ThisSurf));
14515 :
14516 43762 : if (surface.Class == SurfaceClass::IntMass) continue;
14517 :
14518 41478 : auto const &vertex(surface.Vertex);
14519 :
14520 41478 : if (surface.Sides == 3) { // 3-sided polygon
14521 :
14522 183 : centroid = cen(vertex(1), vertex(2), vertex(3));
14523 :
14524 41295 : } else if (surface.Sides == 4) { // 4-sided polygon
14525 :
14526 : // split into 2 3-sided polygons (Triangle 1 and Triangle 2)
14527 41128 : Triangle1(1) = vertex(1);
14528 41128 : Triangle1(2) = vertex(2);
14529 41128 : Triangle1(3) = vertex(3);
14530 41128 : Triangle2(1) = vertex(1);
14531 41128 : Triangle2(2) = vertex(3);
14532 41128 : Triangle2(3) = vertex(4);
14533 :
14534 : // get total Area of quad.
14535 41128 : Real64 TotalArea(surface.GrossArea);
14536 41128 : if (TotalArea <= 0.0) {
14537 : // catch a problem....
14538 0 : ShowWarningError(state, "CalcSurfaceCentroid: zero area surface, for surface=" + surface.Name);
14539 0 : continue;
14540 : }
14541 :
14542 : // get area fraction of triangles.
14543 41128 : Real64 Tri1Area(AreaPolygon(3, Triangle1) / TotalArea);
14544 41128 : Real64 Tri2Area(AreaPolygon(3, Triangle2) / TotalArea);
14545 :
14546 : // check if sum of fractions are slightly greater than 1.0 which is a symptom of the triangles for a non-convex
14547 : // quadralateral using the wrong two triangles
14548 41128 : if ((Tri1Area + Tri2Area) > 1.05) {
14549 :
14550 : // if so repeat the process with the other two possible triangles (notice the vertices are in a different order this
14551 : // time) split into 2 3-sided polygons (Triangle 1 and Triangle 2)
14552 20 : Triangle1(1) = vertex(1);
14553 20 : Triangle1(2) = vertex(2);
14554 20 : Triangle1(3) = vertex(4);
14555 20 : Triangle2(1) = vertex(2);
14556 20 : Triangle2(2) = vertex(3);
14557 20 : Triangle2(3) = vertex(4);
14558 :
14559 : // get area fraction of triangles.
14560 20 : Real64 AreaTriangle1 = AreaPolygon(3, Triangle1);
14561 20 : Real64 AreaTriangle2 = AreaPolygon(3, Triangle2);
14562 20 : TotalArea = AreaTriangle1 + AreaTriangle2;
14563 20 : Tri1Area = AreaTriangle1 / TotalArea;
14564 20 : Tri2Area = AreaTriangle2 / TotalArea;
14565 : }
14566 :
14567 : // get centroid of Triangle 1
14568 82256 : Vector cen1(cen(Triangle1(1), Triangle1(2), Triangle1(3)));
14569 :
14570 : // get centroid of Triangle 2
14571 82256 : Vector cen2(cen(Triangle2(1), Triangle2(2), Triangle2(3)));
14572 :
14573 : // find area weighted combination of the two centroids (coded to avoid temporary Vectors)
14574 41128 : cen1 *= Tri1Area;
14575 41128 : cen2 *= Tri2Area;
14576 41128 : centroid = cen1;
14577 41128 : centroid += cen2;
14578 :
14579 167 : } else if (surface.Sides >= 5) { // multi-sided polygon
14580 : // (Maybe triangulate? For now, use old "z" average method")
14581 : // and X and Y -- straight average
14582 :
14583 : // X1=MINVAL(Surface(ThisSurf)%Vertex(1:Surface(ThisSurf)%Sides)%x)
14584 : // X2=MAXVAL(Surface(ThisSurf)%Vertex(1:Surface(ThisSurf)%Sides)%x)
14585 : // Y1=MINVAL(Surface(ThisSurf)%Vertex(1:Surface(ThisSurf)%Sides)%y)
14586 : // Y2=MAXVAL(Surface(ThisSurf)%Vertex(1:Surface(ThisSurf)%Sides)%y)
14587 : // Z1=MINVAL(Surface(ThisSurf)%Vertex(1:Surface(ThisSurf)%Sides)%z)
14588 : // Z2=MAXVAL(Surface(ThisSurf)%Vertex(1:Surface(ThisSurf)%Sides)%z)
14589 : // Xcm=(X1+X2)/2.0d0
14590 : // Ycm=(Y1+Y2)/2.0d0
14591 : // Zcm=(Z1+Z2)/2.0d0
14592 :
14593 : // Calc centroid as average of surfaces
14594 167 : centroid = 0.0;
14595 1691 : for (int vert = 1; vert <= surface.Sides; ++vert) {
14596 1524 : centroid += vertex(vert);
14597 : }
14598 167 : centroid /= double(surface.Sides);
14599 :
14600 : } else {
14601 :
14602 0 : if (!surface.Name.empty()) {
14603 0 : ShowWarningError(state, "CalcSurfaceCentroid: caught problem with # of sides, for surface=" + surface.Name);
14604 0 : ShowContinueError(state, format("... number of sides must be >= 3, this surface # sides={}", surface.Sides));
14605 : } else {
14606 0 : ShowWarningError(state, format("CalcSurfaceCentroid: caught problem with # of sides, for surface=#{}", ThisSurf));
14607 0 : ShowContinueError(state,
14608 : "...surface name is blank. Examine surfaces -- this may be a problem with ill-formed interzone surfaces.");
14609 0 : ShowContinueError(state, format("... number of sides must be >= 3, this surface # sides={}", surface.Sides));
14610 : }
14611 0 : centroid = 0.0;
14612 : }
14613 :
14614 : // store result in the surface structure in DataSurfaces
14615 41478 : surface.Centroid = centroid;
14616 :
14617 41478 : if (centroid.z < 0.0) {
14618 283 : if (surface.ExtWind || surface.ExtBoundCond == ExternalEnvironment) ++negZcount;
14619 : }
14620 :
14621 : } // loop through surfaces
14622 :
14623 771 : if (negZcount > 0) {
14624 4 : ShowWarningError(state, format("CalcSurfaceCentroid: {} Surfaces have the Z coordinate < 0.", negZcount));
14625 4 : ShowContinueError(state, "...in any calculations, Wind Speed will be 0.0 for these surfaces.");
14626 12 : ShowContinueError(state,
14627 12 : format("...in any calculations, Outside temperatures will be the outside temperature + {:.3R} for these surfaces.",
14628 8 : state.dataEnvrn->WeatherFileTempModCoeff));
14629 4 : ShowContinueError(state, "...that is, these surfaces will have conditions as though at ground level.");
14630 : }
14631 771 : }
14632 :
14633 771 : void SetupShadeSurfacesForSolarCalcs(EnergyPlusData &state)
14634 : {
14635 : // SUBROUTINE INFORMATION:
14636 : // AUTHOR B. Griffith
14637 : // DATE WRITTEN Dec. 2008
14638 : // MODIFIED na
14639 : // RE-ENGINEERED na
14640 :
14641 : // PURPOSE OF THIS SUBROUTINE:
14642 : // determine if Shading surfaces need full solar calcs because they
14643 : // are also used to define geometry of an active solar component.
14644 : // Normally, a shading surface is not included in calculations of incident solar, only shading
14645 :
14646 : // METHODOLOGY EMPLOYED:
14647 : // Mine solar renewables input and collect surface names.
14648 : // find shading surfaces with names that match those in solar objects.
14649 : // setup flags for shading surfaces so that the solar renewables can resuse incident solar calcs
14650 : // new solar component models that use shading surfaces will have to extend the code here.
14651 :
14652 : // Using/Aliasing
14653 :
14654 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
14655 1542 : Array1D_string TmpCandidateSurfaceNames;
14656 1542 : Array1D_string TmpCandidateICSSurfaceNames;
14657 1542 : Array1D_string TmpCandidateICSBCTypeNames;
14658 : int NumCandidateNames;
14659 : int NumOfCollectors;
14660 : int NumOfICSUnits;
14661 : int NumOfFlatPlateUnits;
14662 : int NumPVTs;
14663 : int NumPVs;
14664 : int SurfNum;
14665 : int Found;
14666 : int CollectorNum;
14667 : int PVTnum;
14668 : int PVnum;
14669 : int NumAlphas; // Number of alpha names being passed
14670 : int NumNumbers; // Number of numeric parameters being passed
14671 : int IOStatus;
14672 771 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
14673 : // First collect names of surfaces referenced by active solar components
14674 771 : cCurrentModuleObject = "SolarCollector:FlatPlate:Water";
14675 771 : NumOfFlatPlateUnits = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
14676 771 : cCurrentModuleObject = "SolarCollector:FlatPlate:PhotovoltaicThermal";
14677 771 : NumPVTs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
14678 771 : cCurrentModuleObject = "Generator:Photovoltaic";
14679 771 : NumPVs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
14680 771 : cCurrentModuleObject = "SolarCollector:IntegralCollectorStorage";
14681 771 : NumOfICSUnits = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
14682 :
14683 771 : NumCandidateNames = NumOfFlatPlateUnits + NumPVTs + NumPVs + NumOfICSUnits;
14684 771 : NumOfCollectors = NumOfFlatPlateUnits + NumOfICSUnits;
14685 :
14686 771 : TmpCandidateSurfaceNames.allocate(NumCandidateNames);
14687 771 : TmpCandidateICSSurfaceNames.allocate(NumOfCollectors);
14688 771 : TmpCandidateICSBCTypeNames.allocate(NumOfCollectors);
14689 :
14690 771 : if (NumOfCollectors > 0) {
14691 3 : cCurrentModuleObject = "SolarCollector:FlatPlate:Water";
14692 11 : for (CollectorNum = 1; CollectorNum <= NumOfFlatPlateUnits; ++CollectorNum) {
14693 :
14694 24 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
14695 : cCurrentModuleObject,
14696 : CollectorNum,
14697 8 : state.dataIPShortCut->cAlphaArgs,
14698 : NumAlphas,
14699 8 : state.dataIPShortCut->rNumericArgs,
14700 : NumNumbers,
14701 : IOStatus);
14702 :
14703 8 : TmpCandidateSurfaceNames(CollectorNum) = state.dataIPShortCut->cAlphaArgs(3);
14704 8 : TmpCandidateICSBCTypeNames(CollectorNum) = "";
14705 : }
14706 : }
14707 :
14708 771 : if (NumPVTs > 0) {
14709 1 : cCurrentModuleObject = "SolarCollector:FlatPlate:PhotovoltaicThermal";
14710 11 : for (PVTnum = 1; PVTnum <= NumPVTs; ++PVTnum) {
14711 :
14712 30 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
14713 : cCurrentModuleObject,
14714 : PVTnum,
14715 10 : state.dataIPShortCut->cAlphaArgs,
14716 : NumAlphas,
14717 10 : state.dataIPShortCut->rNumericArgs,
14718 : NumNumbers,
14719 : IOStatus);
14720 :
14721 10 : TmpCandidateSurfaceNames(NumOfFlatPlateUnits + PVTnum) = state.dataIPShortCut->cAlphaArgs(2);
14722 : }
14723 : }
14724 :
14725 771 : if (NumPVs > 0) {
14726 6 : cCurrentModuleObject = "Generator:Photovoltaic";
14727 54 : for (PVnum = 1; PVnum <= NumPVs; ++PVnum) {
14728 144 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
14729 : cCurrentModuleObject,
14730 : PVnum,
14731 48 : state.dataIPShortCut->cAlphaArgs,
14732 : NumAlphas,
14733 48 : state.dataIPShortCut->rNumericArgs,
14734 : NumNumbers,
14735 : IOStatus);
14736 48 : TmpCandidateSurfaceNames(NumOfFlatPlateUnits + NumPVTs + PVnum) = state.dataIPShortCut->cAlphaArgs(2);
14737 : }
14738 : }
14739 :
14740 771 : if (NumOfICSUnits > 0) {
14741 1 : cCurrentModuleObject = "SolarCollector:IntegralCollectorStorage";
14742 3 : for (CollectorNum = 1; CollectorNum <= NumOfICSUnits; ++CollectorNum) {
14743 6 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
14744 : cCurrentModuleObject,
14745 : CollectorNum,
14746 2 : state.dataIPShortCut->cAlphaArgs,
14747 : NumAlphas,
14748 2 : state.dataIPShortCut->rNumericArgs,
14749 : NumNumbers,
14750 : IOStatus);
14751 2 : TmpCandidateSurfaceNames(NumOfFlatPlateUnits + NumPVTs + NumPVs + CollectorNum) = state.dataIPShortCut->cAlphaArgs(3);
14752 2 : TmpCandidateICSSurfaceNames(NumOfFlatPlateUnits + CollectorNum) = state.dataIPShortCut->cAlphaArgs(3);
14753 2 : TmpCandidateICSBCTypeNames(NumOfFlatPlateUnits + CollectorNum) = state.dataIPShortCut->cAlphaArgs(4);
14754 : }
14755 : }
14756 :
14757 : // loop through all the surfaces
14758 44533 : for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
14759 :
14760 43762 : Found = UtilityRoutines::FindItemInList(state.dataSurface->Surface(SurfNum).Name, TmpCandidateSurfaceNames, NumCandidateNames);
14761 43762 : if (Found > 0) {
14762 48 : if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) { // not BIPV, must be a shading surf with solar device
14763 : // Setup missing values to allow shading surfaces to model incident solar and wind
14764 16 : state.dataSurface->Surface(SurfNum).ExtSolar = true;
14765 16 : state.dataSurface->Surface(SurfNum).ExtWind = true;
14766 16 : state.dataSurface->Surface(SurfNum).ViewFactorGround = 0.5 * (1.0 - state.dataSurface->Surface(SurfNum).CosTilt);
14767 : }
14768 : // check if this surface is used for ICS collector mounting and has OthersideCondictionsModel as its
14769 : // boundary condition
14770 48 : if (NumOfICSUnits > 0) {
14771 6 : for (CollectorNum = 1; CollectorNum <= NumOfCollectors; ++CollectorNum) {
14772 10 : if (UtilityRoutines::SameString(state.dataSurface->Surface(SurfNum).Name, TmpCandidateICSSurfaceNames(CollectorNum)) &&
14773 6 : UtilityRoutines::SameString(TmpCandidateICSBCTypeNames(CollectorNum), "OTHERSIDECONDITIONSMODEL")) {
14774 2 : state.dataSurface->SurfIsICS(SurfNum) = true;
14775 2 : state.dataSurface->SurfICSPtr(SurfNum) = CollectorNum;
14776 : }
14777 : }
14778 : }
14779 :
14780 : } // end of IF (Found > 0) Then
14781 : }
14782 771 : }
14783 :
14784 : void
14785 1542 : SetupEnclosuresAndAirBoundaries(EnergyPlusData &state,
14786 : EPVector<DataViewFactorInformation::EnclosureViewFactorInformation> &Enclosures, // Radiant or Solar Enclosures
14787 : SurfaceGeometry::enclosureType const EnclosureType, // Radiant or Solar
14788 : bool &ErrorsFound) // Set to true if errors found
14789 : {
14790 : static constexpr std::string_view RoutineName = "SetupEnclosuresAndAirBoundaries";
14791 1542 : bool anyGroupedSpaces = false;
14792 1542 : bool radiantSetup = false;
14793 1542 : bool solarSetup = false;
14794 3084 : std::string RadiantOrSolar = "";
14795 1542 : int enclosureNum = 0;
14796 1542 : if (EnclosureType == RadiantEnclosures) {
14797 771 : radiantSetup = true;
14798 771 : RadiantOrSolar = "Radiant";
14799 771 : state.dataViewFactor->EnclRadInfo.allocate(state.dataGlobal->numSpaces);
14800 771 : } else if (EnclosureType == SolarEnclosures) {
14801 771 : solarSetup = true;
14802 771 : RadiantOrSolar = "Solar";
14803 771 : state.dataViewFactor->EnclSolInfo.allocate(state.dataGlobal->numSpaces);
14804 : } else {
14805 0 : ShowFatalError(state,
14806 0 : std::string{RoutineName} +
14807 : ": Illegal call to this function. Second argument must be 'RadiantEnclosures' or 'SolarEnclosures'");
14808 : }
14809 1542 : if (std::any_of(state.dataConstruction->Construct.begin(),
14810 1542 : state.dataConstruction->Construct.end(),
14811 11697 : [](Construction::ConstructionProps const &e) { return e.TypeIsAirBoundary; })) {
14812 6 : int errorCount = 0;
14813 336 : for (int surfNum = 1; surfNum <= state.dataSurface->TotSurfaces; ++surfNum) {
14814 330 : auto &surf(state.dataSurface->Surface(surfNum));
14815 330 : if (surf.Construction == 0) continue;
14816 306 : auto &constr(state.dataConstruction->Construct(surf.Construction));
14817 306 : if (!constr.TypeIsAirBoundary) continue;
14818 28 : surf.IsAirBoundarySurf = true;
14819 :
14820 : // Check for invalid air boundary surfaces - valid only on non-adiabatic interzone surfaces
14821 : // Only check this once during radiant setup, skip for solar setup
14822 28 : if (radiantSetup && (surf.ExtBoundCond <= 0 || surf.ExtBoundCond == surfNum)) {
14823 0 : ErrorsFound = true;
14824 0 : if (!state.dataGlobal->DisplayExtraWarnings) {
14825 0 : ++errorCount;
14826 : } else {
14827 0 : ShowSevereError(state,
14828 0 : std::string{RoutineName} + ": Surface=\"" + surf.Name +
14829 : "\" uses Construction:AirBoundary in a non-interzone surface.");
14830 : }
14831 : } else {
14832 : // Process air boundary - set surface properties and set up enclosures
14833 : // Radiant exchange
14834 28 : if (surf.IsAirBoundarySurf) {
14835 : // Boundary is grouped - assign enclosure
14836 28 : state.dataHeatBal->AnyAirBoundary = true;
14837 28 : int thisSideEnclosureNum = 0;
14838 28 : int otherSideEnclosureNum = 0;
14839 28 : if (radiantSetup) {
14840 : // Radiant enclosure setup
14841 14 : constr.IsUsedCTF = false;
14842 14 : surf.HeatTransSurf = false;
14843 14 : surf.HeatTransferAlgorithm = DataSurfaces::HeatTransferModel::AirBoundaryNoHT;
14844 14 : thisSideEnclosureNum = state.dataHeatBal->space(surf.spaceNum).radiantEnclosureNum;
14845 14 : otherSideEnclosureNum =
14846 14 : state.dataHeatBal->space(state.dataSurface->Surface(surf.ExtBoundCond).spaceNum).radiantEnclosureNum;
14847 : } else {
14848 : // Solar enclosure setup
14849 14 : thisSideEnclosureNum = state.dataHeatBal->space(surf.spaceNum).solarEnclosureNum;
14850 14 : otherSideEnclosureNum =
14851 14 : state.dataHeatBal->space(state.dataSurface->Surface(surf.ExtBoundCond).spaceNum).solarEnclosureNum;
14852 : }
14853 28 : anyGroupedSpaces = true;
14854 28 : if ((thisSideEnclosureNum == 0) && (otherSideEnclosureNum == 0)) {
14855 : // Neither zone is assigned to an enclosure, so increment the counter and assign to both
14856 6 : ++enclosureNum;
14857 6 : auto &thisEnclosure(Enclosures(enclosureNum));
14858 6 : thisSideEnclosureNum = enclosureNum;
14859 6 : thisEnclosure.Name = format("{} Enclosure {}", RadiantOrSolar, enclosureNum);
14860 6 : thisEnclosure.spaceNames.push_back(state.dataHeatBal->space(surf.spaceNum).Name);
14861 6 : thisEnclosure.spaceNums.push_back(surf.spaceNum);
14862 6 : thisEnclosure.FloorArea += state.dataHeatBal->space(surf.spaceNum).floorArea;
14863 6 : otherSideEnclosureNum = enclosureNum;
14864 6 : int otherSideSpaceNum = state.dataSurface->Surface(surf.ExtBoundCond).spaceNum;
14865 6 : if (otherSideSpaceNum != surf.spaceNum) {
14866 6 : thisEnclosure.spaceNames.push_back(state.dataHeatBal->space(otherSideSpaceNum).Name);
14867 6 : thisEnclosure.spaceNums.push_back(otherSideSpaceNum);
14868 6 : thisEnclosure.FloorArea += state.dataHeatBal->space(otherSideSpaceNum).floorArea;
14869 : }
14870 6 : if (radiantSetup) {
14871 3 : state.dataHeatBal->space(surf.spaceNum).radiantEnclosureNum = thisSideEnclosureNum;
14872 3 : state.dataHeatBal->space(state.dataSurface->Surface(surf.ExtBoundCond).spaceNum).radiantEnclosureNum =
14873 : otherSideEnclosureNum;
14874 : } else {
14875 3 : thisEnclosure.ExtWindowArea += state.dataHeatBal->space(surf.spaceNum).extWindowArea;
14876 3 : thisEnclosure.TotalSurfArea += state.dataHeatBal->space(surf.spaceNum).totalSurfArea;
14877 3 : if (otherSideSpaceNum != surf.spaceNum) {
14878 3 : thisEnclosure.ExtWindowArea += state.dataHeatBal->space(otherSideSpaceNum).extWindowArea;
14879 3 : thisEnclosure.TotalSurfArea += state.dataHeatBal->space(otherSideSpaceNum).totalSurfArea;
14880 : }
14881 3 : state.dataHeatBal->space(surf.spaceNum).solarEnclosureNum = thisSideEnclosureNum;
14882 3 : state.dataHeatBal->space(state.dataSurface->Surface(surf.ExtBoundCond).spaceNum).solarEnclosureNum =
14883 : otherSideEnclosureNum;
14884 6 : }
14885 22 : } else if (thisSideEnclosureNum == 0) {
14886 : // Other side is assigned, so use that one for both
14887 0 : thisSideEnclosureNum = otherSideEnclosureNum;
14888 0 : auto &thisEnclosure(Enclosures(thisSideEnclosureNum));
14889 0 : thisEnclosure.spaceNames.push_back(state.dataHeatBal->space(surf.spaceNum).Name);
14890 0 : thisEnclosure.spaceNums.push_back(surf.spaceNum);
14891 0 : thisEnclosure.FloorArea += state.dataHeatBal->space(surf.spaceNum).floorArea;
14892 0 : if (radiantSetup) {
14893 0 : state.dataHeatBal->space(surf.spaceNum).radiantEnclosureNum = thisSideEnclosureNum;
14894 : } else {
14895 0 : thisEnclosure.ExtWindowArea += state.dataHeatBal->space(surf.spaceNum).extWindowArea;
14896 0 : thisEnclosure.TotalSurfArea += state.dataHeatBal->space(surf.spaceNum).totalSurfArea;
14897 0 : state.dataHeatBal->space(surf.spaceNum).solarEnclosureNum = thisSideEnclosureNum;
14898 : }
14899 22 : } else if (otherSideEnclosureNum == 0) {
14900 : // This side is assigned, so use that one for both
14901 4 : otherSideEnclosureNum = thisSideEnclosureNum;
14902 4 : auto &thisEnclosure(Enclosures(thisSideEnclosureNum));
14903 4 : thisEnclosure.spaceNames.push_back(state.dataHeatBal->space(state.dataSurface->Surface(surf.ExtBoundCond).spaceNum).Name);
14904 4 : thisEnclosure.spaceNums.push_back(state.dataSurface->Surface(surf.ExtBoundCond).spaceNum);
14905 4 : thisEnclosure.FloorArea += state.dataHeatBal->space(state.dataSurface->Surface(surf.ExtBoundCond).spaceNum).floorArea;
14906 4 : if (radiantSetup) {
14907 2 : state.dataHeatBal->space(state.dataSurface->Surface(surf.ExtBoundCond).spaceNum).radiantEnclosureNum =
14908 : otherSideEnclosureNum;
14909 : } else {
14910 2 : thisEnclosure.ExtWindowArea +=
14911 2 : state.dataHeatBal->space(state.dataSurface->Surface(surf.ExtBoundCond).spaceNum).extWindowArea;
14912 2 : thisEnclosure.TotalSurfArea +=
14913 2 : state.dataHeatBal->space(state.dataSurface->Surface(surf.ExtBoundCond).spaceNum).totalSurfArea;
14914 2 : state.dataHeatBal->space(state.dataSurface->Surface(surf.ExtBoundCond).spaceNum).solarEnclosureNum =
14915 : otherSideEnclosureNum;
14916 : }
14917 18 : } else if (thisSideEnclosureNum != otherSideEnclosureNum) {
14918 : // If both sides are already assigned to an enclosure, then merge the two enclosures
14919 0 : auto &thisEnclosure(Enclosures(thisSideEnclosureNum));
14920 0 : auto &otherEnclosure(Enclosures(otherSideEnclosureNum));
14921 0 : for (const auto &zName : thisEnclosure.spaceNames) {
14922 0 : otherEnclosure.spaceNames.push_back(zName);
14923 : }
14924 0 : for (const auto &zNum : thisEnclosure.spaceNums) {
14925 0 : otherEnclosure.spaceNums.push_back(zNum);
14926 0 : if (radiantSetup) {
14927 0 : state.dataHeatBal->space(zNum).radiantEnclosureNum = otherSideEnclosureNum;
14928 : } else {
14929 0 : state.dataHeatBal->space(zNum).solarEnclosureNum = otherSideEnclosureNum;
14930 : }
14931 : }
14932 0 : otherEnclosure.FloorArea += thisEnclosure.FloorArea;
14933 0 : otherEnclosure.ExtWindowArea += thisEnclosure.ExtWindowArea;
14934 0 : otherEnclosure.TotalSurfArea += thisEnclosure.TotalSurfArea;
14935 : // Move any enclosures beyond thisEnclosure down one slot - at this point all enclosures are named "Radiant
14936 : // Enclosure N"
14937 0 : for (int enclNum = thisSideEnclosureNum; enclNum < enclosureNum; ++enclNum) {
14938 0 : std::string saveName = Enclosures(enclNum).Name;
14939 0 : Enclosures(enclNum) = Enclosures(enclNum + 1);
14940 0 : Enclosures(enclNum).Name = saveName;
14941 0 : for (int sNum : Enclosures(enclNum).spaceNums) {
14942 0 : if (radiantSetup) {
14943 0 : state.dataHeatBal->space(sNum).radiantEnclosureNum = enclNum;
14944 : } else {
14945 0 : state.dataHeatBal->space(sNum).solarEnclosureNum = enclNum;
14946 : }
14947 : }
14948 : }
14949 : // Clear the last rad enclosure and reduce the total number of enclosures by 1
14950 0 : Enclosures(enclosureNum).Name.clear();
14951 0 : Enclosures(enclosureNum).spaceNames.clear();
14952 0 : Enclosures(enclosureNum).spaceNums.clear();
14953 0 : Enclosures(enclosureNum).FloorArea = 0;
14954 0 : Enclosures(enclosureNum).ExtWindowArea = 0;
14955 0 : Enclosures(enclosureNum).TotalSurfArea = 0;
14956 0 : enclosureNum -= 1;
14957 : }
14958 : } else {
14959 0 : ErrorsFound = true;
14960 0 : ShowSevereError(state,
14961 0 : std::string{RoutineName} + ": Surface=" + surf.Name + " uses Construction:AirBoundary with illegal option:");
14962 0 : if (radiantSetup) {
14963 0 : ShowContinueError(state, "Radiant Exchange Method must be either GroupedSpaces or IRTSurface.");
14964 : } else {
14965 0 : ShowContinueError(state, "Solar and Daylighting Method must be either GroupedSpaces or InteriorWindow");
14966 : }
14967 : }
14968 28 : if (solarSetup && constr.TypeIsAirBoundaryMixing) {
14969 : // Set up mixing air boundaries only once, during solar setup
14970 12 : int spaceNum1 = min(surf.spaceNum, state.dataSurface->Surface(surf.ExtBoundCond).spaceNum);
14971 12 : int spaceNum2 = max(surf.spaceNum, state.dataSurface->Surface(surf.ExtBoundCond).spaceNum);
14972 : // This pair already saved?
14973 12 : bool found = false;
14974 24 : for (auto thisAirBoundaryMixing : state.dataHeatBal->airBoundaryMixing) {
14975 18 : if ((spaceNum1 == thisAirBoundaryMixing.space1) && (spaceNum2 == thisAirBoundaryMixing.space2)) {
14976 6 : found = true;
14977 6 : break;
14978 : }
14979 : }
14980 12 : if (!found) {
14981 : // Store the space pairs, schedule, and flow rate to use later to create cross mixing objects
14982 : DataHeatBalance::AirBoundaryMixingSpecs newAirBoundaryMixing;
14983 6 : newAirBoundaryMixing.space1 = spaceNum1;
14984 6 : newAirBoundaryMixing.space2 = spaceNum2;
14985 6 : newAirBoundaryMixing.scheduleIndex = state.dataConstruction->Construct(surf.Construction).AirBoundaryMixingSched;
14986 12 : Real64 mixingVolume = state.dataConstruction->Construct(surf.Construction).AirBoundaryACH *
14987 6 : min(state.dataHeatBal->space(spaceNum1).Volume, state.dataHeatBal->space(spaceNum2).Volume) /
14988 6 : DataGlobalConstants::SecInHour;
14989 6 : newAirBoundaryMixing.mixingVolumeFlowRate = mixingVolume;
14990 6 : state.dataHeatBal->airBoundaryMixing.push_back(newAirBoundaryMixing);
14991 : }
14992 : }
14993 : }
14994 : }
14995 6 : if (errorCount > 0) {
14996 0 : ShowSevereError(state, format("{}: {} surfaces use Construction:AirBoundary in non-interzone surfaces.", RoutineName, errorCount));
14997 0 : ShowContinueError(state, "For explicit details on each use, use Output:Diagnostics,DisplayExtraWarnings;");
14998 : }
14999 : }
15000 : // Check for any spaces defined only by floor surface(s) and group them
15001 11170 : for (auto const &zone : state.dataHeatBal->Zone) {
15002 9628 : int newEnclosureNum = 0;
15003 19264 : for (int const spaceNum : zone.spaceIndexes) {
15004 9636 : int spaceEnclosureNum = 0;
15005 9636 : bool spaceHasOnlyFloors = false;
15006 9636 : if (radiantSetup) {
15007 4818 : spaceEnclosureNum = state.dataHeatBal->space(spaceNum).radiantEnclosureNum;
15008 : } else {
15009 4818 : spaceEnclosureNum = state.dataHeatBal->space(spaceNum).solarEnclosureNum;
15010 : }
15011 9636 : if (spaceEnclosureNum == 0) {
15012 9620 : spaceHasOnlyFloors = true;
15013 9950 : for (int const surfNum : state.dataHeatBal->space(spaceNum).surfaces) {
15014 9946 : if (state.dataSurface->Surface(surfNum).Class == SurfaceClass::IntMass) continue;
15015 9946 : if (state.dataSurface->Surface(surfNum).Class != SurfaceClass::Floor) {
15016 9616 : spaceHasOnlyFloors = false;
15017 9616 : break;
15018 : }
15019 : }
15020 : }
15021 9636 : if (spaceEnclosureNum == 0 && spaceHasOnlyFloors) {
15022 4 : anyGroupedSpaces = true;
15023 4 : if (newEnclosureNum == 0) {
15024 : // Assign one new enclosure for all loose floors in this zone
15025 2 : ++enclosureNum;
15026 2 : newEnclosureNum = enclosureNum;
15027 : }
15028 4 : if (radiantSetup) {
15029 2 : state.dataHeatBal->space(spaceNum).radiantEnclosureNum = enclosureNum;
15030 : } else {
15031 2 : state.dataHeatBal->space(spaceNum).solarEnclosureNum = enclosureNum;
15032 : }
15033 4 : auto &thisEnclosure(Enclosures(enclosureNum));
15034 : // Give this enclosure the zone name and assign this to the zone-remainder space if it exists
15035 4 : thisEnclosure.Name = zone.Name;
15036 4 : thisEnclosure.spaceNames.push_back(state.dataHeatBal->space(spaceNum).Name);
15037 4 : thisEnclosure.spaceNums.push_back(spaceNum);
15038 4 : thisEnclosure.FloorArea = state.dataHeatBal->space(spaceNum).floorArea;
15039 4 : thisEnclosure.ExtWindowArea = state.dataHeatBal->space(spaceNum).extWindowArea;
15040 4 : thisEnclosure.TotalSurfArea = state.dataHeatBal->space(spaceNum).totalSurfArea;
15041 : }
15042 : }
15043 : }
15044 :
15045 1542 : if (anyGroupedSpaces) {
15046 : // All grouped spaces have been assigned to an enclosure, now assign remaining spaces
15047 50 : for (int spaceNum = 1; spaceNum <= state.dataGlobal->numSpaces; ++spaceNum) {
15048 44 : auto &curSpace = state.dataHeatBal->space(spaceNum);
15049 44 : int spaceEnclosureNum = 0;
15050 44 : if (radiantSetup) {
15051 22 : spaceEnclosureNum = curSpace.radiantEnclosureNum;
15052 : } else {
15053 22 : spaceEnclosureNum = curSpace.solarEnclosureNum;
15054 : }
15055 44 : if (spaceEnclosureNum == 0) {
15056 24 : if (UtilityRoutines::SameString(curSpace.Name, state.dataHeatBal->Zone(curSpace.zoneNum).Name + "-Remainder")) {
15057 : // Search for existing enclosure with same name as the zone
15058 2 : spaceEnclosureNum = UtilityRoutines::FindItemInList(state.dataHeatBal->Zone(curSpace.zoneNum).Name, Enclosures);
15059 : }
15060 24 : if (spaceEnclosureNum == 0) {
15061 : // Otherwise add a new one named for the space
15062 22 : ++enclosureNum;
15063 22 : spaceEnclosureNum = enclosureNum;
15064 22 : Enclosures(spaceEnclosureNum).Name = curSpace.Name;
15065 : }
15066 24 : if (radiantSetup) {
15067 12 : curSpace.radiantEnclosureNum = spaceEnclosureNum;
15068 : } else {
15069 12 : curSpace.solarEnclosureNum = spaceEnclosureNum;
15070 : }
15071 24 : auto &thisEnclosure(Enclosures(spaceEnclosureNum));
15072 24 : thisEnclosure.spaceNames.push_back(curSpace.Name);
15073 24 : thisEnclosure.spaceNums.push_back(spaceNum);
15074 24 : thisEnclosure.FloorArea += curSpace.floorArea;
15075 24 : thisEnclosure.ExtWindowArea += curSpace.extWindowArea;
15076 24 : thisEnclosure.TotalSurfArea += curSpace.totalSurfArea;
15077 : }
15078 : }
15079 6 : if (radiantSetup) {
15080 3 : state.dataViewFactor->NumOfRadiantEnclosures = enclosureNum;
15081 : } else {
15082 3 : state.dataViewFactor->NumOfSolarEnclosures = enclosureNum;
15083 : }
15084 : } else {
15085 : // There are no grouped radiant air boundaries, assign each space to it's own radiant enclosure
15086 11128 : for (int spaceNum = 1; spaceNum <= state.dataGlobal->numSpaces; ++spaceNum) {
15087 9592 : auto &thisEnclosure(Enclosures(spaceNum));
15088 9592 : thisEnclosure.Name = state.dataHeatBal->space(spaceNum).Name;
15089 9592 : thisEnclosure.spaceNames.push_back(state.dataHeatBal->space(spaceNum).Name);
15090 9592 : thisEnclosure.spaceNums.push_back(spaceNum);
15091 9592 : thisEnclosure.FloorArea = state.dataHeatBal->space(spaceNum).floorArea;
15092 9592 : if (radiantSetup) {
15093 4796 : state.dataHeatBal->space(spaceNum).radiantEnclosureNum = spaceNum;
15094 : } else {
15095 4796 : state.dataHeatBal->space(spaceNum).solarEnclosureNum = spaceNum;
15096 4796 : thisEnclosure.ExtWindowArea = state.dataHeatBal->space(spaceNum).extWindowArea;
15097 4796 : thisEnclosure.TotalSurfArea = state.dataHeatBal->space(spaceNum).totalSurfArea;
15098 : }
15099 : }
15100 1536 : if (radiantSetup) {
15101 768 : state.dataViewFactor->NumOfRadiantEnclosures = state.dataGlobal->numSpaces;
15102 : } else {
15103 768 : state.dataViewFactor->NumOfSolarEnclosures = state.dataGlobal->numSpaces;
15104 : }
15105 : }
15106 1542 : if (radiantSetup) {
15107 771 : assert(state.dataViewFactor->NumOfRadiantEnclosures <= int(Enclosures.size()));
15108 : } else {
15109 771 : assert(state.dataViewFactor->NumOfSolarEnclosures <= int(Enclosures.size()));
15110 : }
15111 :
15112 : // TODO MJW: For now, set the max and min enclosure numbers for each zone to be used in CalcInteriorRadExchange with ZoneToResimulate
15113 11170 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
15114 19264 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
15115 9636 : if (state.dataHeatBal->Zone(zoneNum).zoneRadEnclosureFirst == -1) { // initial value
15116 4814 : state.dataHeatBal->Zone(zoneNum).zoneRadEnclosureFirst = state.dataHeatBal->space(spaceNum).radiantEnclosureNum;
15117 : } else {
15118 4822 : state.dataHeatBal->Zone(zoneNum).zoneRadEnclosureFirst =
15119 4822 : min(state.dataHeatBal->Zone(zoneNum).zoneRadEnclosureFirst, state.dataHeatBal->space(spaceNum).radiantEnclosureNum);
15120 : }
15121 9636 : state.dataHeatBal->Zone(zoneNum).zoneRadEnclosureLast =
15122 9636 : max(state.dataHeatBal->Zone(zoneNum).zoneRadEnclosureLast, state.dataHeatBal->space(spaceNum).radiantEnclosureNum);
15123 : }
15124 9628 : assert(state.dataHeatBal->Zone(zoneNum).zoneRadEnclosureFirst != -1);
15125 9628 : assert(state.dataHeatBal->Zone(zoneNum).zoneRadEnclosureLast != -1);
15126 9628 : assert(state.dataHeatBal->Zone(zoneNum).zoneRadEnclosureFirst <= state.dataHeatBal->Zone(zoneNum).zoneRadEnclosureLast);
15127 : }
15128 1542 : }
15129 :
15130 40093 : void CheckConvexity(EnergyPlusData &state,
15131 : int const SurfNum, // Current surface number
15132 : int const NSides // Number of sides to figure
15133 : )
15134 : {
15135 :
15136 : // SUBROUTINE INFORMATION:
15137 : // AUTHOR Tyler Hoyt
15138 : // DATE WRITTEN December 2010
15139 : // MODIFIED CR8752 - incorrect note of non-convex polygons
15140 : // RE-ENGINEERED na
15141 :
15142 : // PURPOSE OF THIS SUBROUTINE: This subroutine verifies the convexity of a
15143 : // surface that is exposed to the sun in the case that full shading calculations
15144 : // are required. The calculation conveniently detects collinear points as well,
15145 : // and returns a list of indices that are collinear within the plane of the surface.
15146 :
15147 : // METHODOLOGY EMPLOYED: First the surface is determined to have dimension 2 in
15148 : // either the xy, yz, or xz plane. That plane is selected to do the testing.
15149 : // Vectors representing the edges of the polygon and the perpendicular dot product
15150 : // between adjacent edges are computed. This allows the turning angle to be determined.
15151 : // If the turning angle is greater than pi/2, it turns to the right, and if it is
15152 : // less than pi/2, it turns left. The direction of the turn is stored, and if it
15153 : // changes as the edges are iterated the surface is not convex. Meanwhile it stores
15154 : // the indices of vertices that are collinear and are later removed.
15155 :
15156 : // REFERENCES:
15157 : // http://mathworld.wolfram.com/ConvexPolygon.html
15158 :
15159 : // Using/Aliasing
15160 :
15161 : using namespace DataErrorTracking;
15162 :
15163 40093 : constexpr Real64 TurnThreshold(0.000001); // Sensitivity of convexity test, in radians
15164 :
15165 40093 : Real64 LastTheta = 0.0; // Angle between edge vectors
15166 : bool SignFlag; // Direction of edge turn : true is right, false is left
15167 40093 : bool PrevSignFlag(false); // Container for the sign of the previous iteration's edge turn
15168 40093 : bool PrevSignFlagInitialized(false); // Whether we picked a PrevSignFlag already or not
15169 40093 : auto &X = state.dataSurfaceGeometry->X; // containers for x,y,z vertices of the surface
15170 40093 : auto &Y = state.dataSurfaceGeometry->Y;
15171 40093 : auto &Z = state.dataSurfaceGeometry->Z;
15172 40093 : auto &A = state.dataSurfaceGeometry->A; // containers for convexity test
15173 40093 : auto &B = state.dataSurfaceGeometry->B;
15174 40093 : auto &VertSize = state.dataSurfaceGeometry->VertSize; // size of X,Y,Z,A,B arrays
15175 :
15176 80186 : std::vector<int> surfCollinearVerts; // index of vertices to remove, 1-indexed
15177 40093 : surfCollinearVerts.reserve(NSides + 2);
15178 :
15179 40093 : if (state.dataSurfaceGeometry->CheckConvexityFirstTime) {
15180 737 : X.allocate(state.dataSurface->MaxVerticesPerSurface + 2);
15181 737 : Y.allocate(state.dataSurface->MaxVerticesPerSurface + 2);
15182 737 : Z.allocate(state.dataSurface->MaxVerticesPerSurface + 2);
15183 737 : A.allocate(state.dataSurface->MaxVerticesPerSurface + 2);
15184 737 : B.allocate(state.dataSurface->MaxVerticesPerSurface + 2);
15185 737 : VertSize = state.dataSurface->MaxVerticesPerSurface;
15186 737 : state.dataSurfaceGeometry->CheckConvexityFirstTime = false;
15187 : }
15188 :
15189 40093 : if (NSides > VertSize) {
15190 30 : X.deallocate();
15191 30 : Y.deallocate();
15192 30 : Z.deallocate();
15193 30 : A.deallocate();
15194 30 : B.deallocate();
15195 30 : X.allocate(state.dataSurface->MaxVerticesPerSurface + 2);
15196 30 : Y.allocate(state.dataSurface->MaxVerticesPerSurface + 2);
15197 30 : Z.allocate(state.dataSurface->MaxVerticesPerSurface + 2);
15198 30 : A.allocate(state.dataSurface->MaxVerticesPerSurface + 2);
15199 30 : B.allocate(state.dataSurface->MaxVerticesPerSurface + 2);
15200 30 : VertSize = state.dataSurface->MaxVerticesPerSurface;
15201 : }
15202 :
15203 40093 : auto &surfaceTmp = state.dataSurfaceGeometry->SurfaceTmp(SurfNum);
15204 40093 : auto &vertices = surfaceTmp.Vertex;
15205 :
15206 201160 : for (int n = 1; n <= NSides; ++n) {
15207 161067 : X(n) = vertices(n).x;
15208 161067 : Y(n) = vertices(n).y;
15209 161067 : Z(n) = vertices(n).z;
15210 : }
15211 40093 : X(NSides + 1) = vertices(1).x;
15212 40093 : Y(NSides + 1) = vertices(1).y;
15213 40093 : Z(NSides + 1) = vertices(1).z;
15214 40093 : X(NSides + 2) = vertices(2).x;
15215 40093 : Y(NSides + 2) = vertices(2).y;
15216 40093 : Z(NSides + 2) = vertices(2).z;
15217 :
15218 : // Determine a suitable plane in which to do the tests
15219 40093 : Real64 Det = 0.0;
15220 201160 : for (int n = 1; n <= NSides; ++n) {
15221 161067 : Det += X(n) * Y(n + 1) - X(n + 1) * Y(n);
15222 : }
15223 40093 : if (std::abs(Det) > 1.e-4) {
15224 12926 : A = X;
15225 12926 : B = Y;
15226 : } else {
15227 27167 : Det = 0.0;
15228 135741 : for (int n = 1; n <= NSides; ++n) {
15229 108574 : Det += X(n) * Z(n + 1) - X(n + 1) * Z(n);
15230 : }
15231 27167 : if (std::abs(Det) > 1.e-4) {
15232 18298 : A = X;
15233 18298 : B = Z;
15234 : } else {
15235 8869 : Det = 0.0;
15236 44279 : for (int n = 1; n <= NSides; ++n) {
15237 35410 : Det += Y(n) * Z(n + 1) - Y(n + 1) * Z(n);
15238 : }
15239 8869 : if (std::abs(Det) > 1.e-4) {
15240 8869 : A = Y;
15241 8869 : B = Z;
15242 : } else {
15243 : // This condition should not be reached if the surfaces are guaranteed to be planar already
15244 0 : ShowSevereError(state, "CheckConvexity: Surface=\"" + surfaceTmp.Name + "\" is non-planar.");
15245 0 : ShowContinueError(state, "Coincident Vertices will be removed as possible.");
15246 0 : for (int n = 1; n <= surfaceTmp.Sides; ++n) {
15247 0 : auto const &point(vertices(n));
15248 : static constexpr std::string_view ErrFmt(" ({:8.3F},{:8.3F},{:8.3F})");
15249 0 : ShowContinueError(state, EnergyPlus::format(ErrFmt, point.x, point.y, point.z));
15250 : }
15251 : }
15252 : }
15253 : }
15254 :
15255 199969 : for (int n = 1; n <= NSides; ++n) { // perform convexity test in the plane determined above.
15256 :
15257 279826 : DataVectorTypes::Vector_2d pt0(A(n), B(n));
15258 279826 : DataVectorTypes::Vector_2d pt1(A(n + 1), B(n + 1));
15259 279826 : DataVectorTypes::Vector_2d pt2(A(n + 2), B(n + 2));
15260 :
15261 279826 : DataVectorTypes::Vector_2d V1 = pt1 - pt0;
15262 279826 : DataVectorTypes::Vector_2d V2 = pt2 - pt1;
15263 :
15264 160043 : Real64 V1len = V1.length(); // = norm_L2()
15265 160043 : Real64 V2len = V2.length();
15266 160043 : if (V1len <= 1.e-8 || V2len <= 1.e-8) {
15267 : // At least two points are coincident. Should this happen? GetVertices is supposed to pop these vertices
15268 0 : continue;
15269 : }
15270 160043 : Real64 CrossProd = V1.cross(V2);
15271 160043 : Real64 sinarg = CrossProd / (V1len * V2len);
15272 160043 : if (sinarg < -1.0) {
15273 832 : sinarg = -1.0;
15274 159211 : } else if (sinarg > 1.0) {
15275 627 : sinarg = 1.0;
15276 : }
15277 160043 : Real64 Theta = std::asin(sinarg);
15278 160043 : if (Theta > TurnThreshold) {
15279 79129 : SignFlag = true;
15280 80914 : } else if (Theta < -TurnThreshold) {
15281 80914 : SignFlag = false;
15282 : } else { // std::abs(Theta) < TurnThreshold
15283 : // Store the index of the collinear vertex for removal
15284 0 : int colinearIndex = n + 1;
15285 0 : if (colinearIndex > NSides) {
15286 0 : colinearIndex -= NSides;
15287 : }
15288 0 : if (state.dataGlobal->DisplayExtraWarnings) {
15289 0 : ShowWarningError(
15290 : state,
15291 0 : format("CheckConvexity: Surface=\"{}\", vertex {} is colinear with previous and next.", surfaceTmp.Name, colinearIndex));
15292 : }
15293 0 : ++state.dataErrTracking->TotalCoincidentVertices;
15294 0 : surfCollinearVerts.push_back(colinearIndex);
15295 0 : continue;
15296 : }
15297 :
15298 200136 : if (!PrevSignFlagInitialized) {
15299 40093 : PrevSignFlag = SignFlag;
15300 40093 : LastTheta = Theta;
15301 40093 : PrevSignFlagInitialized = true;
15302 40093 : continue;
15303 : }
15304 :
15305 119950 : if (SignFlag != PrevSignFlag) {
15306 167 : if (state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::Minimal && surfaceTmp.ExtSolar) {
15307 24 : if (state.dataGlobal->DisplayExtraWarnings) {
15308 0 : ShowWarningError(state,
15309 0 : "CheckConvexity: Zone=\"" + state.dataHeatBal->Zone(surfaceTmp.Zone).Name + "\", Surface=\"" +
15310 0 : surfaceTmp.Name + "\" is non-convex.");
15311 0 : int Np1 = n + 1;
15312 0 : if (Np1 > NSides) {
15313 0 : Np1 -= NSides;
15314 : }
15315 0 : int Np2 = n + 2;
15316 0 : if (Np2 > NSides) {
15317 0 : Np2 -= NSides;
15318 : }
15319 0 : ShowContinueError(state, format("...vertex {} to vertex {} to vertex {}", n, Np1, Np2));
15320 0 : ShowContinueError(state, format("...vertex {}=[{:.2R},{:.2R},{:.2R}]", n, X(n), Y(n), Z(n)));
15321 0 : ShowContinueError(state, format("...vertex {}=[{:.2R},{:.2R},{:.2R}]", Np1, X(n + 1), Y(n + 1), Z(n + 1)));
15322 0 : ShowContinueError(state, format("...vertex {}=[{:.2R},{:.2R},{:.2R}]", Np2, X(n + 2), Y(n + 2), Z(n + 2)));
15323 : // ShowContinueError(state, format("...theta angle=[{:.6R}]", Theta));
15324 : // ShowContinueError(state, format("...last theta angle=[{:.6R}]", LastTheta));
15325 : }
15326 : }
15327 167 : surfaceTmp.IsConvex = false;
15328 167 : break;
15329 : }
15330 119783 : PrevSignFlag = SignFlag;
15331 119783 : LastTheta = Theta;
15332 : }
15333 :
15334 : // must check to make sure don't remove NSides below 3
15335 40093 : int M = surfCollinearVerts.size();
15336 40093 : if (M > 0) { // Remove the collinear points determined above
15337 0 : if (NSides - M >= 3) {
15338 0 : surfaceTmp.Sides = NSides - M;
15339 0 : if (state.dataGlobal->DisplayExtraWarnings) {
15340 0 : ShowWarningError(state,
15341 0 : format("CheckConvexity: Surface=\"{}\" has [{}] collinear points that have been removed.", surfaceTmp.Name, M));
15342 : }
15343 : } else { // too many
15344 0 : if (state.dataGlobal->DisplayExtraWarnings) {
15345 0 : ShowWarningError(state, format("CheckConvexity: Surface=\"{}\" has [{}] collinear points.", surfaceTmp.Name, M));
15346 0 : ShowContinueError(state, "...too many to remove all. Will leave the surface with 3 sides. But this is now a degenerate surface");
15347 : }
15348 0 : ++state.dataErrTracking->TotalDegenerateSurfaces;
15349 0 : surfaceTmp.Sides = 3; // max(NSides - M, 3) = 3 since NSide - M is < 3;
15350 0 : surfCollinearVerts.resize(NSides - 3);
15351 : }
15352 :
15353 : // remove duplicated points: For that we construct a new array of vertices, only copying indices that aren't in SurfCollinearVerts
15354 : // Then we move that array into the original one
15355 0 : Array1D<Vector> newVertices;
15356 0 : newVertices.allocate(surfaceTmp.Sides);
15357 :
15358 0 : int n = 0;
15359 0 : for (int i = 1; i <= NSides; ++i) {
15360 0 : if (std::find(surfCollinearVerts.cbegin(), surfCollinearVerts.cend(), i) == surfCollinearVerts.cend()) {
15361 0 : newVertices(++n) = vertices(i);
15362 : }
15363 : }
15364 0 : vertices = std::move(newVertices);
15365 :
15366 0 : if (state.dataGlobal->DisplayExtraWarnings) {
15367 0 : ShowWarningError(state,
15368 0 : format("CheckConvexity: Surface=\"{}\": The vertex points has been reprocessed as Sides = {}",
15369 : surfaceTmp.Name,
15370 0 : surfaceTmp.Sides));
15371 : }
15372 : }
15373 40093 : }
15374 :
15375 41129 : bool isRectangle(EnergyPlusData &state, int const ThisSurf // Surface number
15376 : )
15377 : {
15378 :
15379 : // SUBROUTINE INFORMATION:
15380 : // AUTHOR M.J. Witte
15381 : // DATE WRITTEN October 2015
15382 :
15383 : // PURPOSE: Check if a 4-sided surface is a rectangle
15384 :
15385 : using namespace Vectors;
15386 :
15387 : Real64 Diagonal1; // Length of diagonal of 4-sided figure from vertex 1 to vertex 3 (m)
15388 : Real64 Diagonal2; // Length of diagonal of 4-sided figure from vertex 2 to vertex 4 (m)
15389 : Real64 DotProd; // Dot product of two adjacent sides - to test for right angle
15390 41129 : Real64 const cos89deg = std::cos(89.0 * DataGlobalConstants::DegToRadians); // tolerance for right angle
15391 82258 : Vector Vect32; // normalized vector from vertex 3 to vertex 2
15392 82258 : Vector Vect21; // normalized vector from vertex 2 to vertex 1
15393 :
15394 41129 : Diagonal1 = VecLength(state.dataSurface->Surface(ThisSurf).Vertex(1) - state.dataSurface->Surface(ThisSurf).Vertex(3));
15395 41129 : Diagonal2 = VecLength(state.dataSurface->Surface(ThisSurf).Vertex(2) - state.dataSurface->Surface(ThisSurf).Vertex(4));
15396 : // Test for rectangularity
15397 41129 : if (std::abs(Diagonal1 - Diagonal2) < 0.020) { // This tolerance based on coincident vertex tolerance of 0.01
15398 39744 : Vect32 = VecNormalize(state.dataSurface->Surface(ThisSurf).Vertex(3) - state.dataSurface->Surface(ThisSurf).Vertex(2));
15399 39744 : Vect21 = VecNormalize(state.dataSurface->Surface(ThisSurf).Vertex(2) - state.dataSurface->Surface(ThisSurf).Vertex(1));
15400 39744 : DotProd = dot(Vect32, Vect21);
15401 39744 : if (std::abs(DotProd) <= cos89deg) {
15402 36241 : return true;
15403 : } else {
15404 3503 : return false;
15405 : }
15406 : } else {
15407 1385 : return false;
15408 : }
15409 : }
15410 :
15411 1 : void MakeEquivalentRectangle(EnergyPlusData &state,
15412 : int const SurfNum, // Surface number
15413 : bool &ErrorsFound // Error flag indicator (true if errors found)
15414 : )
15415 : {
15416 : // SUBROUTINE INFORMATION:
15417 : // AUTHOR R. Zhang, LBNL
15418 : // DATE WRITTEN September 2016
15419 : // MODIFIED na
15420 : // RE-ENGINEERED na
15421 :
15422 : // PURPOSE OF THIS SUBROUTINE:
15423 : // Processing of 4-sided but non-rectangular Window, Door or GlassDoor.
15424 : // Calculate the effective height and width of the surface.
15425 : //
15426 : // METHODOLOGY EMPLOYED:
15427 : // Transform the surface into an equivalent rectangular surface with the same area and aspect ratio.
15428 :
15429 : Real64 BaseCosAzimuth;
15430 : Real64 BaseCosTilt;
15431 : Real64 BaseSinAzimuth;
15432 : Real64 BaseSinTilt;
15433 : Real64 SurfWorldAz;
15434 : Real64 SurfTilt;
15435 : Real64 AspectRatio; // Aspect ratio
15436 : Real64 NumSurfSides; // Number of surface sides
15437 : Real64 WidthEff; // Effective width of the surface
15438 : Real64 WidthMax; // X difference between the vertex on the most left and the one on the most right
15439 : Real64 HeightEff; // Effective height of the surface
15440 : Real64 HeightMax; // Y difference between the lowest and toppest vertices
15441 : Real64 Xp;
15442 : Real64 Yp;
15443 : Real64 Zp;
15444 : Real64 XLLC;
15445 : Real64 YLLC;
15446 : Real64 ZLLC;
15447 :
15448 1 : if (SurfNum == 0) {
15449 : // invalid surface
15450 0 : ErrorsFound = true;
15451 0 : return;
15452 1 : } else if (state.dataSurface->Surface(SurfNum).Sides != 4) {
15453 : // the method is designed for 4-sided surface
15454 0 : return;
15455 1 : } else if (isRectangle(state, SurfNum)) {
15456 : // no need to transform
15457 0 : return;
15458 : }
15459 :
15460 1 : SurfWorldAz = state.dataSurface->Surface(SurfNum).Azimuth;
15461 1 : SurfTilt = state.dataSurface->Surface(SurfNum).Tilt;
15462 1 : BaseCosAzimuth = std::cos(SurfWorldAz * DataGlobalConstants::DegToRadians);
15463 1 : BaseSinAzimuth = std::sin(SurfWorldAz * DataGlobalConstants::DegToRadians);
15464 1 : BaseCosTilt = std::cos(SurfTilt * DataGlobalConstants::DegToRadians);
15465 1 : BaseSinTilt = std::sin(SurfTilt * DataGlobalConstants::DegToRadians);
15466 1 : NumSurfSides = state.dataSurface->Surface(SurfNum).Sides;
15467 :
15468 : // Calculate WidthMax and HeightMax
15469 1 : WidthMax = 0.0;
15470 1 : HeightMax = 0.0;
15471 4 : for (int i = 1; i < NumSurfSides; ++i) {
15472 9 : for (int j = i + 1; j <= NumSurfSides; ++j) {
15473 :
15474 6 : Xp = state.dataSurface->Surface(SurfNum).Vertex(j).x - state.dataSurface->Surface(SurfNum).Vertex(i).x;
15475 6 : Yp = state.dataSurface->Surface(SurfNum).Vertex(j).y - state.dataSurface->Surface(SurfNum).Vertex(i).y;
15476 6 : Zp = state.dataSurface->Surface(SurfNum).Vertex(j).z - state.dataSurface->Surface(SurfNum).Vertex(i).z;
15477 :
15478 6 : XLLC = -Xp * BaseCosAzimuth + Yp * BaseSinAzimuth;
15479 6 : YLLC = -Xp * BaseSinAzimuth * BaseCosTilt - Yp * BaseCosAzimuth * BaseCosTilt + Zp * BaseSinTilt;
15480 6 : ZLLC = Xp * BaseSinAzimuth * BaseSinTilt + Yp * BaseCosAzimuth * BaseSinTilt + Zp * BaseCosTilt;
15481 :
15482 6 : if (std::abs(XLLC) > WidthMax) WidthMax = std::abs(XLLC);
15483 6 : if (std::abs(YLLC) > WidthMax) HeightMax = std::abs(YLLC);
15484 : }
15485 : }
15486 :
15487 : // Perform transformation by calculating WidthEff and HeightEff
15488 1 : if ((WidthMax > 0) && (HeightMax > 0)) {
15489 1 : AspectRatio = WidthMax / HeightMax;
15490 : } else {
15491 0 : AspectRatio = 1;
15492 : }
15493 1 : WidthEff = std::sqrt(state.dataSurface->Surface(SurfNum).Area * AspectRatio);
15494 1 : HeightEff = std::sqrt(state.dataSurface->Surface(SurfNum).Area / AspectRatio);
15495 :
15496 : // Assign the effective width and length to the surface
15497 1 : state.dataSurface->Surface(SurfNum).Width = WidthEff;
15498 1 : state.dataSurface->Surface(SurfNum).Height = HeightEff;
15499 : }
15500 :
15501 8432 : void CheckForReversedLayers(EnergyPlusData &state,
15502 : bool &RevLayerDiffs, // true when differences are discovered in interzone constructions
15503 : int const ConstrNum, // construction index
15504 : int const ConstrNumRev, // construction index for reversed construction
15505 : int const TotalLayers // total layers for construction definition
15506 : )
15507 : {
15508 :
15509 8432 : RevLayerDiffs = false;
15510 :
15511 26277 : for (int LayerNo = 1; LayerNo <= TotalLayers; ++LayerNo) {
15512 17847 : auto &thisConstLayer(state.dataConstruction->Construct(ConstrNum).LayerPoint(LayerNo));
15513 17847 : auto &revConstLayer(state.dataConstruction->Construct(ConstrNumRev).LayerPoint(TotalLayers - LayerNo + 1));
15514 17847 : auto &thisMatLay(state.dataMaterial->Material(thisConstLayer));
15515 17847 : auto &revMatLay(state.dataMaterial->Material(revConstLayer));
15516 35692 : if ((thisConstLayer != revConstLayer) || // Not pointing to the same layer
15517 35683 : (thisMatLay.Group == DataHeatBalance::MaterialGroup::WindowGlass) || // Not window glass or glass equivalent layer which have
15518 35676 : (revMatLay.Group == DataHeatBalance::MaterialGroup::WindowGlass) || // to have certain properties flipped from front to back
15519 35676 : (thisMatLay.Group == DataHeatBalance::MaterialGroup::GlassEquivalentLayer) ||
15520 17838 : (revMatLay.Group == DataHeatBalance::MaterialGroup::GlassEquivalentLayer)) {
15521 : // If not point to the same layer, check to see if this is window glass which might need to have
15522 : // front and back material properties reversed.
15523 9 : Real64 constexpr SmallDiff = 0.0001;
15524 16 : if ((thisMatLay.Group == DataHeatBalance::MaterialGroup::WindowGlass) &&
15525 7 : (revMatLay.Group == DataHeatBalance::MaterialGroup::WindowGlass)) {
15526 : // Both layers are window glass, so need to check to see if the properties are reversed
15527 28 : if ((abs(thisMatLay.Thickness - revMatLay.Thickness) > SmallDiff) ||
15528 14 : (abs(thisMatLay.ReflectSolBeamBack - revMatLay.ReflectSolBeamFront) > SmallDiff) ||
15529 14 : (abs(thisMatLay.ReflectSolBeamFront - revMatLay.ReflectSolBeamBack) > SmallDiff) ||
15530 14 : (abs(thisMatLay.TransVis - revMatLay.TransVis) > SmallDiff) ||
15531 14 : (abs(thisMatLay.ReflectVisBeamBack - revMatLay.ReflectVisBeamFront) > SmallDiff) ||
15532 14 : (abs(thisMatLay.ReflectVisBeamFront - revMatLay.ReflectVisBeamBack) > SmallDiff) ||
15533 14 : (abs(thisMatLay.TransThermal - revMatLay.TransThermal) > SmallDiff) ||
15534 14 : (abs(thisMatLay.AbsorpThermalBack - revMatLay.AbsorpThermalFront) > SmallDiff) ||
15535 14 : (abs(thisMatLay.AbsorpThermalFront - revMatLay.AbsorpThermalBack) > SmallDiff) ||
15536 14 : (abs(thisMatLay.Conductivity - revMatLay.Conductivity) > SmallDiff) ||
15537 14 : (abs(thisMatLay.GlassTransDirtFactor - revMatLay.GlassTransDirtFactor) > SmallDiff) ||
15538 14 : (thisMatLay.SolarDiffusing != revMatLay.SolarDiffusing) ||
15539 21 : (abs(thisMatLay.YoungModulus - revMatLay.YoungModulus) > SmallDiff) ||
15540 7 : (abs(thisMatLay.PoissonsRatio - revMatLay.PoissonsRatio) > SmallDiff)) {
15541 0 : RevLayerDiffs = true;
15542 0 : break; // exit when diff
15543 : } // If none of the above conditions is met, then these should be the same layers in reverse (RevLayersDiffs = false)
15544 2 : } else if ((thisMatLay.Group == DataHeatBalance::MaterialGroup::GlassEquivalentLayer) &&
15545 0 : (revMatLay.Group == DataHeatBalance::MaterialGroup::GlassEquivalentLayer)) {
15546 0 : if ((abs(thisMatLay.TausBackBeamBeam - revMatLay.TausFrontBeamBeam) > SmallDiff) ||
15547 0 : (abs(thisMatLay.TausFrontBeamBeam - revMatLay.TausBackBeamBeam) > SmallDiff) ||
15548 0 : (abs(thisMatLay.ReflBackBeamBeam - revMatLay.ReflFrontBeamBeam) > SmallDiff) ||
15549 0 : (abs(thisMatLay.ReflFrontBeamBeam - revMatLay.ReflBackBeamBeam) > SmallDiff) ||
15550 0 : (abs(thisMatLay.TausBackBeamBeamVis - revMatLay.TausFrontBeamBeamVis) > SmallDiff) ||
15551 0 : (abs(thisMatLay.TausFrontBeamBeamVis - revMatLay.TausBackBeamBeamVis) > SmallDiff) ||
15552 0 : (abs(thisMatLay.ReflBackBeamBeamVis - revMatLay.ReflFrontBeamBeamVis) > SmallDiff) ||
15553 0 : (abs(thisMatLay.ReflFrontBeamBeamVis - revMatLay.ReflBackBeamBeamVis) > SmallDiff) ||
15554 0 : (abs(thisMatLay.TausBackBeamDiff - revMatLay.TausFrontBeamDiff) > SmallDiff) ||
15555 0 : (abs(thisMatLay.TausFrontBeamDiff - revMatLay.TausBackBeamDiff) > SmallDiff) ||
15556 0 : (abs(thisMatLay.ReflBackBeamDiff - revMatLay.ReflFrontBeamDiff) > SmallDiff) ||
15557 0 : (abs(thisMatLay.ReflFrontBeamDiff - revMatLay.ReflBackBeamDiff) > SmallDiff) ||
15558 0 : (abs(thisMatLay.TausBackBeamDiffVis - revMatLay.TausFrontBeamDiffVis) > SmallDiff) ||
15559 0 : (abs(thisMatLay.TausFrontBeamDiffVis - revMatLay.TausBackBeamDiffVis) > SmallDiff) ||
15560 0 : (abs(thisMatLay.ReflBackBeamDiffVis - revMatLay.ReflFrontBeamDiffVis) > SmallDiff) ||
15561 0 : (abs(thisMatLay.ReflFrontBeamDiffVis - revMatLay.ReflBackBeamDiffVis) > SmallDiff) ||
15562 0 : (abs(thisMatLay.TausDiffDiff - revMatLay.TausDiffDiff) > SmallDiff) ||
15563 0 : (abs(thisMatLay.ReflBackDiffDiff - revMatLay.ReflFrontDiffDiff) > SmallDiff) ||
15564 0 : (abs(thisMatLay.ReflFrontDiffDiff - revMatLay.ReflBackDiffDiff) > SmallDiff) ||
15565 0 : (abs(thisMatLay.TausDiffDiffVis - revMatLay.TausDiffDiffVis) > SmallDiff) ||
15566 0 : (abs(thisMatLay.ReflBackDiffDiffVis - revMatLay.ReflFrontDiffDiffVis) > SmallDiff) ||
15567 0 : (abs(thisMatLay.ReflFrontDiffDiffVis - revMatLay.ReflBackDiffDiffVis) > SmallDiff) ||
15568 0 : (abs(thisMatLay.TausThermal - revMatLay.TausThermal) > SmallDiff) ||
15569 0 : (abs(thisMatLay.EmissThermalBack - revMatLay.EmissThermalFront) > SmallDiff) ||
15570 0 : (abs(thisMatLay.EmissThermalFront - revMatLay.EmissThermalBack) > SmallDiff) ||
15571 0 : (abs(thisMatLay.Resistance - revMatLay.Resistance) > SmallDiff)) {
15572 0 : RevLayerDiffs = true;
15573 0 : break; // exit when diff
15574 : } // If none of the above conditions is met, then these should be the same layers in reverse (RevLayersDiffs = false)
15575 : } else {
15576 : // Other material types do not have reversed constructions so if they are not the same layer there is a problem
15577 : // (RevLayersDiffs = true)
15578 2 : RevLayerDiffs = true;
15579 2 : break; // exit when diff
15580 : } // End check of whether or not these are WindowGlass
15581 : } // else: thisConstLayer is the same as revConstLayer--so there is no problem (RevLayersDiffs = false)
15582 : }
15583 8432 : }
15584 :
15585 : } // namespace SurfaceGeometry
15586 :
15587 2313 : } // namespace EnergyPlus
|