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 : // EnergyPlus headers
49 : #include <EnergyPlus/BITF.hh>
50 : #include <EnergyPlus/Construction.hh>
51 : #include <EnergyPlus/Data/EnergyPlusData.hh>
52 : #include <EnergyPlus/DataEnvironment.hh>
53 : #include <EnergyPlus/DataHeatBalSurface.hh>
54 : #include <EnergyPlus/DataHeatBalance.hh>
55 : #include <EnergyPlus/DataSurfaces.hh>
56 : #include <EnergyPlus/General.hh>
57 : #include <EnergyPlus/Material.hh>
58 : #include <EnergyPlus/UtilityRoutines.hh>
59 : #include <EnergyPlus/WindowManager.hh>
60 :
61 : // Windows library headers
62 : #include <WCEMultiLayerOptics.hpp>
63 : #include <WCETarcog.hpp>
64 :
65 : // EnergyPlus headers
66 : #include <EnergyPlus/WindowManagerExteriorThermal.hh>
67 :
68 : namespace EnergyPlus {
69 :
70 : using namespace DataEnvironment;
71 : using namespace DataSurfaces;
72 : using namespace DataHeatBalance;
73 : using namespace General;
74 :
75 : namespace WindowManager {
76 :
77 : /////////////////////////////////////////////////////////////////////////////////////////
78 4032 : void CalcWindowHeatBalanceExternalRoutines(EnergyPlusData &state,
79 : int const SurfNum, // Surface number
80 : Real64 const HextConvCoeff, // Outside air film conductance coefficient
81 : Real64 &SurfInsideTemp, // Inside window surface temperature
82 : Real64 &SurfOutsideTemp // Outside surface temperature (C)
83 : )
84 : {
85 : // SUBROUTINE INFORMATION:
86 : // AUTHOR Simon Vidanovic
87 : // DATE WRITTEN July 2016
88 : // MODIFIED na
89 : // RE-ENGINEERED na
90 :
91 : // PURPOSE OF THIS SUBROUTINE:
92 : // Main wrapper routine to pick-up data from EnergyPlus and then call Windows-CalcEngine routines
93 : // to obtain results
94 :
95 4032 : auto &window(state.dataSurface->SurfaceWindow(SurfNum));
96 4032 : auto &surface(state.dataSurface->Surface(SurfNum));
97 4032 : auto ConstrNum = surface.Construction;
98 4032 : auto &construction(state.dataConstruction->Construct(ConstrNum));
99 :
100 4032 : auto const solutionTolerance = 0.02;
101 :
102 : // Tarcog thermal system for solving heat transfer through the window
103 4032 : const auto activeConstrNum{CWCEHeatTransferFactory::getActiveConstructionNumber(state, surface, SurfNum)};
104 8064 : auto aFactory = CWCEHeatTransferFactory(state, surface, SurfNum, activeConstrNum);
105 8064 : auto aSystem = aFactory.getTarcogSystem(state, HextConvCoeff);
106 4032 : aSystem->setTolerance(solutionTolerance);
107 :
108 : // get previous timestep temperatures solution for faster iterations
109 8064 : std::vector<Real64> Guess;
110 4032 : auto totSolidLayers = construction.TotSolidLayers;
111 :
112 : // Interior and exterior shading layers have gas between them and IGU but that gas
113 : // was not part of construction so it needs to be increased by one
114 4032 : if (ANY_SHADE_SCREEN(state.dataSurface->SurfWinShadingFlag(SurfNum)) || ANY_BLIND(state.dataSurface->SurfWinShadingFlag(SurfNum))) {
115 2688 : ++totSolidLayers;
116 : }
117 :
118 20160 : for (auto k = 1; k <= 2 * totSolidLayers; ++k) {
119 16128 : Guess.push_back(state.dataSurface->SurfaceWindow(SurfNum).ThetaFace(k));
120 : }
121 :
122 : try {
123 4032 : aSystem->setInitialGuess(Guess);
124 4032 : aSystem->solve();
125 0 : } catch (const std::exception &ex) {
126 0 : ShowSevereError(state, "Error in Windows Calculation Engine Exterior Module.");
127 0 : ShowContinueError(state, ex.what());
128 : }
129 :
130 8064 : auto aLayers = aSystem->getSolidLayers();
131 4032 : auto i = 1;
132 12096 : for (const auto &aLayer : aLayers) {
133 8064 : Real64 aTemp = 0;
134 24192 : for (auto aSide : FenestrationCommon::EnumSide()) {
135 16128 : aTemp = aLayer->getTemperature(aSide);
136 16128 : state.dataWindowManager->thetas[i - 1] = aTemp;
137 16128 : if (i == 1) {
138 4032 : SurfOutsideTemp = aTemp - DataGlobalConstants::KelvinConv;
139 : }
140 16128 : ++i;
141 : }
142 8064 : SurfInsideTemp = aTemp - DataGlobalConstants::KelvinConv;
143 8064 : if (ANY_INTERIOR_SHADE_BLIND(state.dataSurface->SurfWinShadingFlag(SurfNum))) {
144 : Real64 EffShBlEmiss;
145 : Real64 EffGlEmiss;
146 5376 : if (state.dataSurface->SurfWinMovableSlats(SurfNum)) {
147 0 : EffShBlEmiss =
148 0 : General::InterpGeneral(window.EffShBlindEmiss(state.dataSurface->SurfWinSlatsAngIndex(SurfNum)),
149 0 : window.EffShBlindEmiss(std::min(MaxSlatAngs, state.dataSurface->SurfWinSlatsAngIndex(SurfNum) + 1)),
150 0 : state.dataSurface->SurfWinSlatsAngInterpFac(SurfNum));
151 0 : EffGlEmiss =
152 0 : General::InterpGeneral(window.EffGlassEmiss(state.dataSurface->SurfWinSlatsAngIndex(SurfNum)),
153 0 : window.EffGlassEmiss(std::min(MaxSlatAngs, state.dataSurface->SurfWinSlatsAngIndex(SurfNum) + 1)),
154 0 : state.dataSurface->SurfWinSlatsAngInterpFac(SurfNum));
155 : } else {
156 5376 : EffShBlEmiss = state.dataSurface->SurfaceWindow(SurfNum).EffShBlindEmiss(1);
157 5376 : EffGlEmiss = state.dataSurface->SurfaceWindow(SurfNum).EffGlassEmiss(1);
158 : }
159 5376 : state.dataSurface->SurfWinEffInsSurfTemp(SurfNum) =
160 10752 : (EffShBlEmiss * SurfInsideTemp +
161 16128 : EffGlEmiss * (state.dataWindowManager->thetas[2 * totSolidLayers - 3] - state.dataWindowManager->TKelvin)) /
162 5376 : (EffShBlEmiss + EffGlEmiss);
163 : }
164 : }
165 :
166 4032 : state.dataHeatBalSurf->SurfHConvInt(SurfNum) = aSystem->getHc(Tarcog::ISO15099::Environment::Indoor);
167 4032 : if (ANY_INTERIOR_SHADE_BLIND(state.dataSurface->SurfWinShadingFlag(SurfNum)) || aFactory.isInteriorShade()) {
168 : // It is not clear why EnergyPlus keeps this interior calculations separately for interior shade. This does create different
169 : // solution from heat transfer from tarcog itself. Need to confirm with LBNL team about this approach. Note that heat flow
170 : // through shade (consider case when openings are zero) is different from heat flow obtained by these equations. Will keep
171 : // these calculations just to confirm that current exterior engine is giving close results to what is in here. (Simon)
172 2688 : auto totLayers = aLayers.size();
173 2688 : state.dataWindowManager->nglface = 2 * totLayers - 2;
174 2688 : state.dataWindowManager->nglfacep = state.dataWindowManager->nglface + 2;
175 5376 : auto aShadeLayer = aLayers[totLayers - 1];
176 5376 : auto aGlassLayer = aLayers[totLayers - 2];
177 2688 : auto ShadeArea = state.dataSurface->Surface(SurfNum).Area + state.dataSurface->SurfWinDividerArea(SurfNum);
178 5376 : auto frontSurface = aShadeLayer->getSurface(FenestrationCommon::Side::Front);
179 5376 : auto backSurface = aShadeLayer->getSurface(FenestrationCommon::Side::Back);
180 2688 : auto EpsShIR1 = frontSurface->getEmissivity();
181 2688 : auto EpsShIR2 = backSurface->getEmissivity();
182 2688 : auto TauShIR = frontSurface->getTransmittance();
183 2688 : auto RhoShIR1 = max(0.0, 1.0 - TauShIR - EpsShIR1);
184 2688 : auto RhoShIR2 = max(0.0, 1.0 - TauShIR - EpsShIR2);
185 2688 : auto glassEmiss = aGlassLayer->getSurface(FenestrationCommon::Side::Back)->getEmissivity();
186 2688 : auto RhoGlIR2 = 1.0 - glassEmiss;
187 2688 : auto ShGlReflFacIR = 1.0 - RhoGlIR2 * RhoShIR1;
188 2688 : auto rmir = state.dataSurface->SurfWinIRfromParentZone(SurfNum) + state.dataHeatBalSurf->SurfQdotRadHVACInPerArea(SurfNum);
189 : auto NetIRHeatGainShade =
190 5376 : ShadeArea * EpsShIR2 *
191 5376 : (state.dataWindowManager->sigma * pow(state.dataWindowManager->thetas[state.dataWindowManager->nglfacep - 1], 4) - rmir) +
192 5376 : EpsShIR1 * (state.dataWindowManager->sigma * pow(state.dataWindowManager->thetas[state.dataWindowManager->nglfacep - 2], 4) - rmir) *
193 2688 : RhoGlIR2 * TauShIR / ShGlReflFacIR;
194 : auto NetIRHeatGainGlass =
195 2688 : ShadeArea * (glassEmiss * TauShIR / ShGlReflFacIR) *
196 5376 : (state.dataWindowManager->sigma * pow(state.dataWindowManager->thetas[state.dataWindowManager->nglface - 1], 4) - rmir);
197 2688 : auto tind = surface.getInsideAirTemperature(state, SurfNum) + DataGlobalConstants::KelvinConv;
198 2688 : auto ConvHeatGainFrZoneSideOfShade = ShadeArea * state.dataHeatBalSurf->SurfHConvInt(SurfNum) *
199 2688 : (state.dataWindowManager->thetas[state.dataWindowManager->nglfacep - 1] - tind);
200 2688 : state.dataSurface->SurfWinHeatGain(SurfNum) =
201 2688 : state.dataSurface->SurfWinTransSolar(SurfNum) + ConvHeatGainFrZoneSideOfShade + NetIRHeatGainGlass + NetIRHeatGainShade;
202 :
203 2688 : state.dataSurface->SurfWinGainIRGlazToZoneRep(SurfNum) = NetIRHeatGainGlass;
204 :
205 : // Effective shade and glass emissivities that are used later for energy calculations.
206 : // This needs to be checked as well. (Simon)
207 2688 : auto EffShBlEmiss = EpsShIR1 * (1.0 + RhoGlIR2 * TauShIR / (1.0 - RhoGlIR2 * RhoShIR2));
208 2688 : state.dataSurface->SurfaceWindow(SurfNum).EffShBlindEmiss = EffShBlEmiss;
209 :
210 2688 : auto EffGlEmiss = glassEmiss * TauShIR / (1.0 - RhoGlIR2 * RhoShIR2);
211 2688 : state.dataSurface->SurfaceWindow(SurfNum).EffGlassEmiss = EffGlEmiss;
212 :
213 2688 : auto glassTemperature = aGlassLayer->getSurface(FenestrationCommon::Side::Back)->getTemperature();
214 2688 : state.dataSurface->SurfWinEffInsSurfTemp(SurfNum) =
215 2688 : (EffShBlEmiss * SurfInsideTemp + EffGlEmiss * (glassTemperature - DataGlobalConstants::KelvinConv)) / (EffShBlEmiss + EffGlEmiss);
216 :
217 : } else {
218 : // Another adoptation to old source that looks suspicious. Check if heat flow through
219 : // window is actually matching these values. (Simon)
220 :
221 : //
222 1344 : auto totLayers = aLayers.size();
223 2688 : auto aGlassLayer = aLayers[totLayers - 1];
224 2688 : auto backSurface = aGlassLayer->getSurface(FenestrationCommon::Side::Back);
225 :
226 1344 : auto h_cin = aSystem->getHc(Tarcog::ISO15099::Environment::Indoor);
227 : auto ConvHeatGainFrZoneSideOfGlass =
228 1344 : surface.Area * h_cin * (backSurface->getTemperature() - aSystem->getAirTemperature(Tarcog::ISO15099::Environment::Indoor));
229 :
230 1344 : auto rmir = state.dataSurface->SurfWinIRfromParentZone(SurfNum) + state.dataHeatBalSurf->SurfQdotRadHVACInPerArea(SurfNum);
231 : auto NetIRHeatGainGlass =
232 1344 : surface.Area * backSurface->getEmissivity() * (state.dataWindowManager->sigma * pow(backSurface->getTemperature(), 4) - rmir);
233 :
234 1344 : state.dataSurface->SurfWinEffInsSurfTemp(SurfNum) =
235 1344 : aLayers[totLayers - 1]->getTemperature(FenestrationCommon::Side::Back) - state.dataWindowManager->TKelvin;
236 2688 : state.dataSurface->SurfaceWindow(SurfNum).EffGlassEmiss =
237 4032 : aLayers[totLayers - 1]->getSurface(FenestrationCommon::Side::Back)->getEmissivity();
238 :
239 1344 : state.dataSurface->SurfWinHeatGain(SurfNum) =
240 1344 : state.dataSurface->SurfWinTransSolar(SurfNum) + ConvHeatGainFrZoneSideOfGlass + NetIRHeatGainGlass;
241 1344 : state.dataSurface->SurfWinGainConvGlazToZoneRep(SurfNum) = ConvHeatGainFrZoneSideOfGlass;
242 1344 : state.dataSurface->SurfWinGainIRGlazToZoneRep(SurfNum) = NetIRHeatGainGlass;
243 : }
244 :
245 4032 : auto TransDiff = construction.TransDiff;
246 4032 : state.dataSurface->SurfWinLossSWZoneToOutWinRep(SurfNum) =
247 4032 : state.dataHeatBal->EnclSolQSWRad(state.dataSurface->Surface(SurfNum).SolarEnclIndex) * surface.Area * TransDiff;
248 4032 : state.dataSurface->SurfWinHeatGain(SurfNum) -= state.dataSurface->SurfWinLossSWZoneToOutWinRep(SurfNum);
249 :
250 10752 : for (auto k = 1; k <= surface.getTotLayers(state); ++k) {
251 6720 : state.dataSurface->SurfaceWindow(SurfNum).ThetaFace(2 * k - 1) = state.dataWindowManager->thetas[2 * k - 2];
252 6720 : state.dataSurface->SurfaceWindow(SurfNum).ThetaFace(2 * k) = state.dataWindowManager->thetas[2 * k - 1];
253 :
254 : // temperatures for reporting
255 6720 : state.dataHeatBal->SurfWinFenLaySurfTempFront(SurfNum, k) = state.dataWindowManager->thetas[2 * k - 2] - DataGlobalConstants::KelvinConv;
256 6720 : state.dataHeatBal->SurfWinFenLaySurfTempBack(SurfNum, k) = state.dataWindowManager->thetas[2 * k - 1] - DataGlobalConstants::KelvinConv;
257 : }
258 4032 : }
259 :
260 : Real64
261 41 : GetIGUUValueForNFRCReport(EnergyPlusData &state, const int surfNum, const int constrNum, const Real64 windowWidth, const Real64 windowHeight)
262 : {
263 41 : const auto tilt{90.0};
264 :
265 41 : auto &surface(state.dataSurface->Surface(surfNum));
266 82 : auto aFactory = CWCEHeatTransferFactory(state, surface, surfNum, constrNum);
267 :
268 82 : const auto winterGlassUnit = aFactory.getTarcogSystemForReporting(state, false, windowWidth, windowHeight, tilt);
269 :
270 82 : return winterGlassUnit->getUValue();
271 : }
272 :
273 41 : Real64 GetSHGCValueForNFRCReporting(EnergyPlusData &state, int surfNum, int constrNum, Real64 windowWidth, Real64 windowHeight)
274 : {
275 41 : const auto tilt{90.0};
276 :
277 41 : auto &surface(state.dataSurface->Surface(surfNum));
278 82 : auto aFactory = CWCEHeatTransferFactory(state, surface, surfNum, constrNum);
279 :
280 82 : const auto summerGlassUnit = aFactory.getTarcogSystemForReporting(state, true, windowWidth, windowHeight, tilt);
281 82 : return summerGlassUnit->getSHGC(state.dataConstruction->Construct(surface.Construction).SolTransNorm);
282 : }
283 :
284 422 : void GetWindowAssemblyNfrcForReport(EnergyPlusData &state,
285 : int const surfNum,
286 : int constrNum,
287 : Real64 windowWidth,
288 : Real64 windowHeight,
289 : EnergyPlus::DataSurfaces::NfrcVisionType vision,
290 : Real64 &uvalue,
291 : Real64 &shgc,
292 : Real64 &vt)
293 : {
294 422 : auto &surface(state.dataSurface->Surface(surfNum));
295 422 : auto &frameDivider(state.dataSurface->FrameDivider(surface.FrameDivider));
296 :
297 844 : auto aFactory = CWCEHeatTransferFactory(state, surface, surfNum, constrNum);
298 :
299 1266 : for (bool isSummer : {false, true}) {
300 844 : constexpr auto framehExtConvCoeff{30.0};
301 844 : constexpr auto framehIntConvCoeff{8.0};
302 844 : const auto tilt{90.0};
303 :
304 1688 : auto insulGlassUnit = aFactory.getTarcogSystemForReporting(state, isSummer, windowWidth, windowHeight, tilt);
305 :
306 844 : const double centerOfGlassUvalue = insulGlassUnit->getUValue();
307 :
308 1688 : auto winterGlassUnit = aFactory.getTarcogSystemForReporting(state, false, windowWidth, windowHeight, tilt);
309 :
310 844 : const double frameUvalue = aFactory.overallUfactorFromFilmsAndCond(frameDivider.FrameConductance, framehIntConvCoeff, framehExtConvCoeff);
311 844 : const double frameEdgeUValue{winterGlassUnit->getUValue() * frameDivider.FrEdgeToCenterGlCondRatio}; // not sure about this
312 844 : const double frameProjectedDimension{frameDivider.FrameWidth};
313 844 : const double frameWettedLength{frameProjectedDimension + frameDivider.FrameProjectionIn};
314 844 : const double frameAbsorptance{frameDivider.FrameSolAbsorp};
315 :
316 844 : Tarcog::ISO15099::FrameData frameData{frameUvalue, frameEdgeUValue, frameProjectedDimension, frameWettedLength, frameAbsorptance};
317 :
318 : const double dividerUvalue =
319 844 : aFactory.overallUfactorFromFilmsAndCond(frameDivider.DividerConductance, framehIntConvCoeff, framehExtConvCoeff);
320 844 : const double dividerEdgeUValue{centerOfGlassUvalue * frameDivider.DivEdgeToCenterGlCondRatio}; // not sure about this
321 844 : const double dividerProjectedDimension{frameDivider.DividerWidth};
322 844 : const double dividerWettedLength{dividerProjectedDimension + frameDivider.DividerProjectionIn};
323 844 : const double dividerAbsorptance{frameDivider.DividerSolAbsorp};
324 844 : const int numHorizDividers{frameDivider.HorDividers};
325 844 : const int numVertDividers{frameDivider.VertDividers};
326 :
327 : Tarcog::ISO15099::FrameData dividerData{
328 844 : dividerUvalue, dividerEdgeUValue, dividerProjectedDimension, dividerWettedLength, dividerAbsorptance};
329 :
330 844 : const auto tVis{state.dataConstruction->Construct(constrNum).VisTransNorm};
331 844 : const auto tSol{state.dataConstruction->Construct(constrNum).SolTransNorm};
332 :
333 844 : if (vision == EnergyPlus::DataSurfaces::NfrcVisionType::Single) {
334 1660 : auto window = Tarcog::ISO15099::WindowSingleVision(windowWidth, windowHeight, tVis, tSol, insulGlassUnit);
335 830 : window.setFrameTop(frameData);
336 830 : window.setFrameBottom(frameData);
337 830 : window.setFrameLeft(frameData);
338 830 : window.setFrameRight(frameData);
339 830 : window.setDividers(dividerData, numHorizDividers, numVertDividers);
340 :
341 830 : if (isSummer) {
342 415 : vt = window.vt();
343 415 : shgc = window.shgc();
344 : } else {
345 415 : uvalue = window.uValue();
346 : }
347 14 : } else if (vision == EnergyPlus::DataSurfaces::NfrcVisionType::DualHorizontal) {
348 : auto window =
349 0 : Tarcog::ISO15099::DualVisionHorizontal(windowWidth, windowHeight, tVis, tSol, insulGlassUnit, tVis, tSol, insulGlassUnit);
350 0 : window.setFrameLeft(frameData);
351 0 : window.setFrameRight(frameData);
352 0 : window.setFrameBottomLeft(frameData);
353 0 : window.setFrameBottomRight(frameData);
354 0 : window.setFrameTopLeft(frameData);
355 0 : window.setFrameTopRight(frameData);
356 0 : window.setFrameMeetingRail(frameData);
357 0 : window.setDividers(dividerData, numHorizDividers, numVertDividers);
358 :
359 0 : if (isSummer) {
360 0 : vt = window.vt();
361 0 : shgc = window.shgc();
362 : } else {
363 0 : uvalue = window.uValue();
364 : }
365 14 : } else if (vision == EnergyPlus::DataSurfaces::NfrcVisionType::DualVertical) {
366 28 : auto window = Tarcog::ISO15099::DualVisionVertical(windowWidth, windowHeight, tVis, tSol, insulGlassUnit, tVis, tSol, insulGlassUnit);
367 14 : window.setFrameTop(frameData);
368 14 : window.setFrameBottom(frameData);
369 14 : window.setFrameTopLeft(frameData);
370 14 : window.setFrameTopRight(frameData);
371 14 : window.setFrameBottomLeft(frameData);
372 14 : window.setFrameBottomRight(frameData);
373 14 : window.setFrameMeetingRail(frameData);
374 14 : window.setDividers(dividerData, numHorizDividers, numVertDividers);
375 :
376 14 : if (isSummer) {
377 7 : vt = window.vt();
378 7 : shgc = window.shgc();
379 : } else {
380 7 : uvalue = window.uValue();
381 : }
382 : } else {
383 0 : auto window = Tarcog::ISO15099::WindowSingleVision(windowWidth, windowHeight, tVis, tSol, insulGlassUnit);
384 0 : window.setFrameTop(frameData);
385 0 : window.setFrameBottom(frameData);
386 0 : window.setFrameLeft(frameData);
387 0 : window.setFrameRight(frameData);
388 0 : window.setDividers(dividerData, numHorizDividers, numVertDividers);
389 :
390 0 : if (isSummer) {
391 0 : vt = window.vt();
392 0 : shgc = window.shgc();
393 : } else {
394 0 : uvalue = window.uValue();
395 : }
396 : }
397 : }
398 422 : }
399 :
400 : /////////////////////////////////////////////////////////////////////////////////////////
401 : // CWCEHeatTransferFactory
402 : /////////////////////////////////////////////////////////////////////////////////////////
403 :
404 4536 : CWCEHeatTransferFactory::CWCEHeatTransferFactory(EnergyPlusData &state, SurfaceData const &surface, int const t_SurfNum, int const t_ConstrNum)
405 4536 : : m_Surface(surface), m_Window(state.dataSurface->SurfaceWindow(t_SurfNum)), m_ShadePosition(ShadePosition::NoShade), m_SurfNum(t_SurfNum),
406 9072 : m_SolidLayerIndex(0), m_ConstructionNumber(t_ConstrNum), m_TotLay(getNumOfLayers(state)), m_InteriorBSDFShade(false), m_ExteriorShade(false)
407 : {
408 7726 : if (!state.dataConstruction->Construct(m_ConstructionNumber).WindowTypeBSDF &&
409 3190 : state.dataSurface->SurfWinShadingFlag.size() >= static_cast<size_t>(m_SurfNum)) {
410 3190 : if (ANY_SHADE_SCREEN(state.dataSurface->SurfWinShadingFlag(m_SurfNum)) || ANY_BLIND(state.dataSurface->SurfWinShadingFlag(m_SurfNum))) {
411 2688 : m_ConstructionNumber = state.dataSurface->SurfWinActiveShadedConstruction(m_SurfNum);
412 2688 : m_TotLay = getNumOfLayers(state);
413 : }
414 : }
415 4536 : const auto ShadeFlag{getShadeType(state, m_ConstructionNumber)};
416 :
417 4536 : if (ANY_INTERIOR_SHADE_BLIND(ShadeFlag)) {
418 2718 : m_ShadePosition = ShadePosition::Interior;
419 : }
420 :
421 4536 : if (ANY_EXTERIOR_SHADE_BLIND_SCREEN(ShadeFlag)) {
422 6 : m_ShadePosition = ShadePosition::Exterior;
423 : }
424 :
425 4536 : if (ANY_BETWEENGLASS_SHADE_BLIND(ShadeFlag)) {
426 3 : m_ShadePosition = ShadePosition::Between;
427 : }
428 4536 : }
429 :
430 : /////////////////////////////////////////////////////////////////////////////////////////
431 4032 : std::shared_ptr<Tarcog::ISO15099::CSingleSystem> CWCEHeatTransferFactory::getTarcogSystem(EnergyPlusData &state, Real64 const t_HextConvCoeff)
432 : {
433 8064 : auto Indoor = getIndoor(state);
434 8064 : auto Outdoor = getOutdoor(state, t_HextConvCoeff);
435 8064 : auto aIGU = getIGU();
436 :
437 : // pick-up all layers and put them in IGU (this includes gap layers as well)
438 13440 : for (auto i = 0; i < m_TotLay; ++i) {
439 18816 : auto aLayer = getIGULayer(state, i + 1);
440 9408 : assert(aLayer != nullptr);
441 : // IDF for "standard" windows do not insert gas between glass and shade. Tarcog needs that gas
442 : // and it will be created here
443 9408 : if (m_ShadePosition == ShadePosition::Interior && i == m_TotLay - 1) {
444 5376 : auto aAirLayer = getShadeToGlassLayer(state, i + 1);
445 2688 : aIGU.addLayer(aAirLayer);
446 : }
447 9408 : aIGU.addLayer(aLayer);
448 9408 : if (m_ShadePosition == ShadePosition::Exterior && i == 0) {
449 0 : auto aAirLayer = getShadeToGlassLayer(state, i + 1);
450 0 : aIGU.addLayer(aAirLayer);
451 : }
452 : }
453 :
454 4032 : auto aSystem = std::make_shared<Tarcog::ISO15099::CSingleSystem>(aIGU, Indoor, Outdoor);
455 :
456 8064 : return aSystem;
457 : }
458 :
459 1770 : std::shared_ptr<Tarcog::ISO15099::IIGUSystem> CWCEHeatTransferFactory::getTarcogSystemForReporting(
460 : EnergyPlusData &state, bool const useSummerConditions, const Real64 width, const Real64 height, const Real64 tilt)
461 : {
462 3540 : auto Indoor = getIndoorNfrc(useSummerConditions);
463 3540 : auto Outdoor = getOutdoorNfrc(useSummerConditions);
464 3540 : auto aIGU = getIGU(width, height, tilt);
465 :
466 1770 : m_SolidLayerIndex = 0;
467 : // pick-up all layers and put them in IGU (this includes gap layers as well)
468 5876 : for (auto i = 0; i < m_TotLay; ++i) {
469 8212 : auto aLayer = getIGULayer(state, i + 1);
470 4106 : assert(aLayer != nullptr);
471 : // IDF for "standard" windows do not insert gas between glass and shade. Tarcog needs that gas
472 : // and it will be created here
473 4106 : if (m_ShadePosition == ShadePosition::Interior && i == m_TotLay - 1) {
474 120 : auto aAirLayer = getShadeToGlassLayer(state, i + 1);
475 60 : aIGU.addLayer(aAirLayer);
476 : }
477 4106 : aIGU.addLayer(aLayer);
478 4106 : if (m_ShadePosition == ShadePosition::Exterior && i == 0) {
479 24 : auto aAirLayer = getShadeToGlassLayer(state, i + 1);
480 12 : aIGU.addLayer(aAirLayer);
481 : }
482 : }
483 :
484 3540 : return std::make_shared<Tarcog::ISO15099::CSystem>(aIGU, Indoor, Outdoor);
485 : }
486 :
487 : /////////////////////////////////////////////////////////////////////////////////////////
488 14930 : Material::MaterialProperties *CWCEHeatTransferFactory::getLayerMaterial(EnergyPlusData &state, int const t_Index) const
489 : {
490 14930 : auto ConstrNum = m_ConstructionNumber;
491 :
492 : // BSDF window do not have special shading flag
493 25804 : if (!state.dataConstruction->Construct(ConstrNum).WindowTypeBSDF &&
494 10874 : state.dataSurface->SurfWinShadingFlag.size() >= static_cast<size_t>(m_SurfNum)) {
495 10874 : if (ANY_SHADE_SCREEN(state.dataSurface->SurfWinShadingFlag(m_SurfNum)) || ANY_BLIND(state.dataSurface->SurfWinShadingFlag(m_SurfNum))) {
496 6720 : ConstrNum = state.dataSurface->SurfWinActiveShadedConstruction(m_SurfNum);
497 : }
498 : }
499 :
500 14930 : auto &construction(state.dataConstruction->Construct(ConstrNum));
501 14930 : const auto LayPtr = construction.LayerPoint(t_Index);
502 14930 : return &state.dataMaterial->Material(LayPtr);
503 : }
504 :
505 : /////////////////////////////////////////////////////////////////////////////////////////
506 13514 : std::shared_ptr<Tarcog::ISO15099::CBaseIGULayer> CWCEHeatTransferFactory::getIGULayer(EnergyPlusData &state, int const t_Index)
507 : {
508 13514 : std::shared_ptr<Tarcog::ISO15099::CBaseIGULayer> aLayer = nullptr;
509 :
510 13514 : auto material = getLayerMaterial(state, t_Index);
511 :
512 13514 : auto matGroup = material->Group;
513 :
514 13514 : if (BITF_TEST_ANY(BITF(matGroup),
515 : BITF(DataHeatBalance::MaterialGroup::WindowGlass) | BITF(DataHeatBalance::MaterialGroup::WindowSimpleGlazing) |
516 : BITF(DataHeatBalance::MaterialGroup::WindowBlind) | BITF(DataHeatBalance::MaterialGroup::Shade) |
517 : BITF(DataHeatBalance::MaterialGroup::Screen) | BITF(DataHeatBalance::MaterialGroup::ComplexWindowShade))) {
518 11038 : ++m_SolidLayerIndex;
519 11038 : aLayer = getSolidLayer(state, *material, m_SolidLayerIndex);
520 2476 : } else if (matGroup == DataHeatBalance::MaterialGroup::WindowGas || matGroup == DataHeatBalance::MaterialGroup::WindowGasMixture) {
521 1124 : aLayer = getGapLayer(*material);
522 1352 : } else if (matGroup == DataHeatBalance::MaterialGroup::ComplexWindowGap) {
523 1352 : aLayer = getComplexGapLayer(state, *material);
524 : }
525 :
526 13514 : return aLayer;
527 : }
528 :
529 : /////////////////////////////////////////////////////////////////////////////////////////
530 7224 : int CWCEHeatTransferFactory::getNumOfLayers(EnergyPlusData &state) const
531 : {
532 7224 : return state.dataConstruction->Construct(m_ConstructionNumber).TotLayers;
533 : }
534 :
535 : /////////////////////////////////////////////////////////////////////////////////////////
536 : std::shared_ptr<Tarcog::ISO15099::CBaseIGULayer>
537 11038 : CWCEHeatTransferFactory::getSolidLayer(EnergyPlusData &state, Material::MaterialProperties const &material, int const t_Index)
538 : {
539 : // SUBROUTINE INFORMATION:
540 : // AUTHOR Simon Vidanovic
541 : // DATE WRITTEN July 2016
542 : // MODIFIED na
543 : // RE-ENGINEERED na
544 :
545 : // PURPOSE OF THIS SUBROUTINE:
546 : // Creates solid layer object from material properties in EnergyPlus
547 11038 : auto emissFront = 0.0;
548 11038 : auto emissBack = 0.0;
549 11038 : auto transThermalFront = 0.0;
550 11038 : auto transThermalBack = 0.0;
551 11038 : auto thickness = 0.0;
552 11038 : auto conductivity = 0.0;
553 11038 : auto createOpenness = false;
554 11038 : auto Atop = 0.0;
555 11038 : auto Abot = 0.0;
556 11038 : auto Aleft = 0.0;
557 11038 : auto Aright = 0.0;
558 11038 : auto Afront = 0.0;
559 :
560 11038 : if (material.Group == DataHeatBalance::MaterialGroup::WindowGlass || material.Group == DataHeatBalance::MaterialGroup::WindowSimpleGlazing) {
561 8264 : emissFront = material.AbsorpThermalFront;
562 8264 : emissBack = material.AbsorpThermalBack;
563 8264 : transThermalFront = material.TransThermal;
564 8264 : transThermalBack = material.TransThermal;
565 8264 : thickness = material.Thickness;
566 8264 : conductivity = material.Conductivity;
567 : }
568 11038 : if (material.Group == DataHeatBalance::MaterialGroup::WindowBlind) {
569 1350 : auto blNum = state.dataSurface->SurfWinBlindNumber(m_SurfNum);
570 2700 : auto blind = state.dataHeatBal->Blind(blNum);
571 1350 : thickness = blind.SlatThickness;
572 1350 : conductivity = blind.SlatConductivity;
573 1350 : Atop = blind.BlindTopOpeningMult;
574 1350 : Abot = blind.BlindBottomOpeningMult;
575 1350 : Aleft = blind.BlindLeftOpeningMult;
576 1350 : Aright = blind.BlindRightOpeningMult;
577 1350 : Afront = state.dataSurface->SurfWinBlindAirFlowPermeability(m_SurfNum);
578 4050 : emissFront = InterpSlatAng(
579 2700 : state.dataSurface->SurfWinSlatAngThisTS(m_SurfNum), state.dataSurface->SurfWinMovableSlats(m_SurfNum), blind.IRFrontEmiss);
580 4050 : emissBack = InterpSlatAng(
581 2700 : state.dataSurface->SurfWinSlatAngThisTS(m_SurfNum), state.dataSurface->SurfWinMovableSlats(m_SurfNum), blind.IRBackEmiss);
582 4050 : transThermalFront = InterpSlatAng(
583 2700 : state.dataSurface->SurfWinSlatAngThisTS(m_SurfNum), state.dataSurface->SurfWinMovableSlats(m_SurfNum), blind.IRFrontTrans);
584 4050 : transThermalBack = InterpSlatAng(
585 2700 : state.dataSurface->SurfWinSlatAngThisTS(m_SurfNum), state.dataSurface->SurfWinMovableSlats(m_SurfNum), blind.IRBackTrans);
586 1350 : if (t_Index == 1) {
587 0 : m_ExteriorShade = true;
588 : }
589 : }
590 11038 : if (material.Group == DataHeatBalance::MaterialGroup::Shade) {
591 1416 : emissFront = material.AbsorpThermal;
592 1416 : emissBack = material.AbsorpThermal;
593 1416 : transThermalFront = material.TransThermal;
594 1416 : transThermalBack = material.TransThermal;
595 1416 : thickness = material.Thickness;
596 1416 : conductivity = material.Conductivity;
597 1416 : Atop = material.WinShadeTopOpeningMult;
598 1416 : Abot = material.WinShadeBottomOpeningMult;
599 1416 : Aleft = material.WinShadeLeftOpeningMult;
600 1416 : Aright = material.WinShadeRightOpeningMult;
601 1416 : Afront = material.WinShadeAirFlowPermeability;
602 1416 : if (t_Index == 1) {
603 12 : m_ExteriorShade = true;
604 : }
605 : }
606 11038 : if (material.Group == DataHeatBalance::MaterialGroup::Screen) {
607 : // Simon: Existing code already takes into account geometry of Woven and scales down
608 : // emissivity for openning area.
609 0 : emissFront = material.AbsorpThermal;
610 0 : emissBack = material.AbsorpThermal;
611 0 : transThermalFront = material.TransThermal;
612 0 : transThermalBack = material.TransThermal;
613 0 : thickness = material.Thickness;
614 0 : conductivity = material.Conductivity;
615 0 : Atop = material.WinShadeTopOpeningMult;
616 0 : Abot = material.WinShadeBottomOpeningMult;
617 0 : Aleft = material.WinShadeLeftOpeningMult;
618 0 : Aright = material.WinShadeRightOpeningMult;
619 0 : Afront = material.WinShadeAirFlowPermeability;
620 0 : if (t_Index == 1) {
621 0 : m_ExteriorShade = true;
622 : }
623 : }
624 11038 : if (material.Group == DataHeatBalance::MaterialGroup::ComplexWindowShade) {
625 8 : auto shdPtr = material.ComplexShadePtr;
626 8 : auto &shade(state.dataHeatBal->ComplexShade(shdPtr));
627 8 : thickness = shade.Thickness;
628 8 : conductivity = shade.Conductivity;
629 8 : emissFront = shade.FrontEmissivity;
630 8 : emissBack = shade.BackEmissivity;
631 8 : transThermalFront = shade.IRTransmittance;
632 8 : transThermalBack = shade.IRTransmittance;
633 8 : Afront = shade.FrontOpeningMultiplier;
634 8 : Atop = shade.TopOpeningMultiplier;
635 8 : Abot = shade.BottomOpeningMultiplier;
636 8 : Aleft = shade.LeftOpeningMultiplier;
637 8 : Aright = shade.RightOpeningMultiplier;
638 8 : createOpenness = true;
639 8 : m_InteriorBSDFShade = ((2 * t_Index - 1) == m_TotLay);
640 : }
641 :
642 22076 : std::shared_ptr<Tarcog::ISO15099::ISurface> frontSurface = std::make_shared<Tarcog::ISO15099::CSurface>(emissFront, transThermalFront);
643 22076 : std::shared_ptr<Tarcog::ISO15099::ISurface> backSurface = std::make_shared<Tarcog::ISO15099::CSurface>(emissBack, transThermalBack);
644 22076 : auto aSolidLayer = std::make_shared<Tarcog::ISO15099::CIGUSolidLayer>(thickness, conductivity, frontSurface, backSurface);
645 11038 : if (createOpenness) {
646 16 : auto aOpenings = std::make_shared<Tarcog::ISO15099::CShadeOpenings>(Atop, Abot, Aleft, Aright, Afront, Afront);
647 8 : aSolidLayer = std::make_shared<Tarcog::ISO15099::CIGUShadeLayer>(aSolidLayer, aOpenings);
648 : }
649 : static constexpr double standardizedRadiationIntensity{783.0};
650 11038 : if (state.dataWindowManager->inExtWindowModel->isExternalLibraryModel()) {
651 8064 : auto &surface(state.dataSurface->Surface(m_SurfNum));
652 8064 : const auto ConstrNum{getActiveConstructionNumber(state, surface, m_SurfNum)};
653 : std::shared_ptr<MultiLayerOptics::CMultiLayerScattered> aLayer =
654 16128 : CWindowConstructionsSimplified::instance().getEquivalentLayer(state, FenestrationCommon::WavelengthRange::Solar, ConstrNum);
655 :
656 : // Report is done for normal incidence
657 8064 : const auto Theta{0.0};
658 8064 : const auto Phi{0.0};
659 : const auto absCoeff =
660 8064 : aLayer->getAbsorptanceLayer(t_Index, FenestrationCommon::Side::Front, FenestrationCommon::ScatteringSimple::Diffuse, Theta, Phi);
661 8064 : aSolidLayer->setSolarAbsorptance(absCoeff, standardizedRadiationIntensity);
662 : } else {
663 2974 : const auto absCoeff{state.dataConstruction->Construct(state.dataSurface->Surface(m_SurfNum).Construction).AbsDiff(t_Index)};
664 2974 : aSolidLayer->setSolarAbsorptance(absCoeff, standardizedRadiationIntensity);
665 : }
666 22076 : return aSolidLayer;
667 : }
668 :
669 : /////////////////////////////////////////////////////////////////////////////////////////
670 1124 : std::shared_ptr<Tarcog::ISO15099::CBaseIGULayer> CWCEHeatTransferFactory::getGapLayer(Material::MaterialProperties const &material) const
671 : {
672 : // SUBROUTINE INFORMATION:
673 : // AUTHOR Simon Vidanovic
674 : // DATE WRITTEN July 2016
675 : // MODIFIED na
676 : // RE-ENGINEERED na
677 :
678 : // PURPOSE OF THIS SUBROUTINE:
679 : // Creates gap layer object from material properties in EnergyPlus
680 1124 : auto const pres = 1e5; // Old code uses this constant pressure
681 1124 : auto thickness = material.Thickness;
682 2248 : auto aGas = getGas(material);
683 1124 : std::shared_ptr<Tarcog::ISO15099::CBaseIGULayer> aLayer = std::make_shared<Tarcog::ISO15099::CIGUGapLayer>(thickness, pres, aGas);
684 2248 : return aLayer;
685 : }
686 :
687 : /////////////////////////////////////////////////////////////////////////////////////////
688 2760 : std::shared_ptr<Tarcog::ISO15099::CBaseIGULayer> CWCEHeatTransferFactory::getShadeToGlassLayer(EnergyPlusData &state, int const t_Index) const
689 : {
690 : // SUBROUTINE INFORMATION:
691 : // AUTHOR Simon Vidanovic
692 : // DATE WRITTEN August 2016
693 : // MODIFIED na
694 : // RE-ENGINEERED na
695 :
696 : // PURPOSE OF THIS SUBROUTINE:
697 : // Creates gap layer object from material properties in EnergyPlus
698 2760 : auto const pres = 1e5; // Old code uses this constant pressure
699 5520 : auto aGas = getAir();
700 2760 : auto thickness = 0.0;
701 :
702 2760 : const auto ShadeFlag{getShadeType(state, m_ConstructionNumber)};
703 :
704 2760 : if (ShadeFlag == WinShadingType::IntBlind || ShadeFlag == WinShadingType::ExtBlind) {
705 1344 : thickness = state.dataHeatBal->Blind(state.dataSurface->SurfWinBlindNumber(m_SurfNum)).BlindToGlassDist;
706 : }
707 2760 : if (ShadeFlag == WinShadingType::IntShade || ShadeFlag == WinShadingType::ExtShade || ShadeFlag == WinShadingType::ExtScreen) {
708 1416 : const auto material = getLayerMaterial(state, t_Index);
709 1416 : thickness = material->WinShadeToGlassDist;
710 : }
711 2760 : std::shared_ptr<Tarcog::ISO15099::CBaseIGULayer> aLayer = std::make_shared<Tarcog::ISO15099::CIGUGapLayer>(thickness, pres, aGas);
712 5520 : return aLayer;
713 : }
714 :
715 : /////////////////////////////////////////////////////////////////////////////////////////
716 1352 : std::shared_ptr<Tarcog::ISO15099::CBaseIGULayer> CWCEHeatTransferFactory::getComplexGapLayer(EnergyPlusData &state,
717 : Material::MaterialProperties const &material) const
718 : {
719 : // SUBROUTINE INFORMATION:
720 : // AUTHOR Simon Vidanovic
721 : // DATE WRITTEN July 2016
722 : // MODIFIED na
723 : // RE-ENGINEERED na
724 :
725 : // PURPOSE OF THIS SUBROUTINE:
726 : // Creates gap layer object from material properties in EnergyPlus
727 1352 : auto const pres = 1e5; // Old code uses this constant pressure
728 1352 : auto thickness = material.Thickness;
729 1352 : auto gasPointer = material.GasPointer;
730 1352 : auto &gasMaterial(state.dataMaterial->Material(gasPointer));
731 2704 : auto aGas = getGas(gasMaterial);
732 1352 : std::shared_ptr<Tarcog::ISO15099::CBaseIGULayer> aLayer = std::make_shared<Tarcog::ISO15099::CIGUGapLayer>(thickness, pres, aGas);
733 2704 : return aLayer;
734 : }
735 :
736 : /////////////////////////////////////////////////////////////////////////////////////////
737 2476 : Gases::CGas CWCEHeatTransferFactory::getGas(Material::MaterialProperties const &material) const
738 : {
739 : // SUBROUTINE INFORMATION:
740 : // AUTHOR Simon Vidanovic
741 : // DATE WRITTEN July 2016
742 : // MODIFIED na
743 : // RE-ENGINEERED
744 : // April 2021: April 2021: Return of CGas instead of pointer to it
745 :
746 : // PURPOSE OF THIS SUBROUTINE:
747 : // Creates gap layer object from material properties in EnergyPlus
748 2476 : const auto numGases = material.NumberOfGasesInMixture;
749 2476 : auto const vacuumCoeff = 1.4; // Load vacuum coefficient once it is implemented (Simon).
750 4952 : const auto gasName = material.Name;
751 2476 : Gases::CGas aGas;
752 4994 : for (auto i = 1; i <= numGases; ++i) {
753 2518 : auto wght = material.GasWght(i);
754 2518 : auto fract = material.GasFract(i);
755 5036 : std::vector<double> gcon;
756 5036 : std::vector<double> gvis;
757 5036 : std::vector<double> gcp;
758 10072 : for (auto j = 1; j <= 3; ++j) {
759 7554 : gcon.push_back(material.GasCon(j, i));
760 7554 : gvis.push_back(material.GasVis(j, i));
761 7554 : gcp.push_back(material.GasCp(j, i));
762 : }
763 2518 : auto aCon = Gases::CIntCoeff(gcon[0], gcon[1], gcon[2]);
764 2518 : auto aCp = Gases::CIntCoeff(gcp[0], gcp[1], gcp[2]);
765 2518 : auto aVis = Gases::CIntCoeff(gvis[0], gvis[1], gvis[2]);
766 5036 : auto aData = Gases::CGasData(gasName, wght, vacuumCoeff, aCp, aCon, aVis);
767 2518 : aGas.addGasItem(fract, aData);
768 : }
769 4952 : return aGas;
770 : }
771 :
772 : /////////////////////////////////////////////////////////////////////////////////////////
773 2760 : Gases::CGas CWCEHeatTransferFactory::getAir()
774 : {
775 : // SUBROUTINE INFORMATION:
776 : // AUTHOR Simon Vidanovic
777 : // DATE WRITTEN August 2016
778 : // MODIFIED na
779 : // RE-ENGINEERED
780 : // April 2021: CGas return from the function instead of pointer to it
781 :
782 : // PURPOSE OF THIS SUBROUTINE:
783 : // Creates air gas layer for tarcog routines
784 2760 : return {};
785 : }
786 :
787 : /////////////////////////////////////////////////////////////////////////////////////////
788 4032 : std::shared_ptr<Tarcog::ISO15099::CEnvironment> CWCEHeatTransferFactory::getIndoor(EnergyPlusData &state) const
789 : {
790 : // SUBROUTINE INFORMATION:
791 : // AUTHOR Simon Vidanovic
792 : // DATE WRITTEN July 2016
793 : // MODIFIED na
794 : // RE-ENGINEERED na
795 :
796 : // PURPOSE OF THIS SUBROUTINE:
797 : // Creates indoor environment object from surface properties in EnergyPlus
798 4032 : auto tin = m_Surface.getInsideAirTemperature(state, m_SurfNum) + DataGlobalConstants::KelvinConv;
799 4032 : auto hcin = state.dataHeatBalSurf->SurfHConvInt(m_SurfNum);
800 :
801 4032 : auto IR = state.dataSurface->SurfWinIRfromParentZone(m_SurfNum) + state.dataHeatBalSurf->SurfQdotRadHVACInPerArea(m_SurfNum);
802 :
803 : std::shared_ptr<Tarcog::ISO15099::CEnvironment> Indoor =
804 4032 : std::make_shared<Tarcog::ISO15099::CIndoorEnvironment>(tin, state.dataEnvrn->OutBaroPress);
805 4032 : Indoor->setHCoeffModel(Tarcog::ISO15099::BoundaryConditionsCoeffModel::CalculateH, hcin);
806 4032 : Indoor->setEnvironmentIR(IR);
807 4032 : return Indoor;
808 : }
809 :
810 : /////////////////////////////////////////////////////////////////////////////////////////
811 4032 : std::shared_ptr<Tarcog::ISO15099::CEnvironment> CWCEHeatTransferFactory::getOutdoor(EnergyPlusData &state, const Real64 t_Hext) const
812 : {
813 : // SUBROUTINE INFORMATION:
814 : // AUTHOR Simon Vidanovic
815 : // DATE WRITTEN July 2016
816 : // MODIFIED na
817 : // RE-ENGINEERED na
818 :
819 : // PURPOSE OF THIS SUBROUTINE:
820 : // Creates outdoor environment object from surface properties in EnergyPlus
821 4032 : double tout = m_Surface.getOutsideAirTemperature(state, m_SurfNum) + DataGlobalConstants::KelvinConv;
822 4032 : double IR = m_Surface.getOutsideIR(state, m_SurfNum);
823 : // double dirSolRad = SurfQRadSWOutIncident( t_SurfNum ) + QS( Surface( t_SurfNum ).Zone );
824 4032 : double swRadiation = m_Surface.getSWIncident(state, m_SurfNum);
825 4032 : double tSky = state.dataEnvrn->SkyTempKelvin;
826 4032 : double airSpeed = 0.0;
827 4032 : if (m_Surface.ExtWind) {
828 4032 : airSpeed = state.dataSurface->SurfOutWindSpeed(m_SurfNum);
829 : }
830 4032 : double fclr = 1 - state.dataEnvrn->CloudFraction;
831 4032 : Tarcog::ISO15099::AirHorizontalDirection airDirection = Tarcog::ISO15099::AirHorizontalDirection::Windward;
832 8064 : std::shared_ptr<Tarcog::ISO15099::CEnvironment> Outdoor = std::make_shared<Tarcog::ISO15099::COutdoorEnvironment>(
833 8064 : tout, airSpeed, swRadiation, airDirection, tSky, Tarcog::ISO15099::SkyModel::AllSpecified, state.dataEnvrn->OutBaroPress, fclr);
834 4032 : Outdoor->setHCoeffModel(Tarcog::ISO15099::BoundaryConditionsCoeffModel::HcPrescribed, t_Hext);
835 4032 : Outdoor->setEnvironmentIR(IR);
836 4032 : return Outdoor;
837 : }
838 :
839 : /////////////////////////////////////////////////////////////////////////////////////////
840 4032 : Tarcog::ISO15099::CIGU CWCEHeatTransferFactory::getIGU() const
841 : {
842 : // SUBROUTINE INFORMATION:
843 : // AUTHOR Simon Vidanovic
844 : // DATE WRITTEN July 2016
845 : // MODIFIED na
846 : // RE-ENGINEERED
847 : // April 2021: Return CIGU object rather than pointer to it
848 :
849 : // PURPOSE OF THIS SUBROUTINE:
850 : // Creates IGU object from surface properties in EnergyPlus
851 :
852 4032 : return {m_Surface.Width, m_Surface.Height, m_Surface.Tilt};
853 : }
854 :
855 1770 : Tarcog::ISO15099::CIGU CWCEHeatTransferFactory::getIGU(double width, double height, double tilt)
856 : {
857 : // SUBROUTINE INFORMATION:
858 : // AUTHOR Simon Vidanovic
859 : // DATE WRITTEN November 2021
860 : // MODIFIED na
861 : // RE-ENGINEERED
862 : // April 2021: Return CIGU object rather than pointer to it
863 :
864 : // PURPOSE OF THIS SUBROUTINE:
865 : // Creates IGU object for given width, height and tilt
866 :
867 1770 : return {width, height, tilt};
868 : }
869 :
870 : int
871 12096 : CWCEHeatTransferFactory::getActiveConstructionNumber(EnergyPlusData &state, EnergyPlus::DataSurfaces::SurfaceData const &surface, int t_SurfNum)
872 : {
873 12096 : auto result{surface.Construction};
874 12096 : const auto ShadeFlag = state.dataSurface->SurfWinShadingFlag(t_SurfNum);
875 :
876 12096 : if (ANY_SHADE_SCREEN(ShadeFlag) || ANY_BLIND(ShadeFlag)) {
877 8064 : result = state.dataSurface->SurfWinActiveShadedConstruction(t_SurfNum);
878 : }
879 :
880 12096 : return result;
881 : }
882 :
883 : /////////////////////////////////////////////////////////////////////////////////////////
884 1344 : bool CWCEHeatTransferFactory::isInteriorShade() const
885 : {
886 1344 : return m_InteriorBSDFShade;
887 : }
888 :
889 1770 : std::shared_ptr<Tarcog::ISO15099::CEnvironment> CWCEHeatTransferFactory::getOutdoorNfrc(bool const useSummerConditions)
890 : {
891 : // NFRC 100 Section 4.3.1
892 1770 : auto airTemperature{-18.0 + DataGlobalConstants::KelvinConv}; // Kelvins
893 1770 : auto airSpeed{5.5}; // meters per second
894 1770 : auto tSky{-18.0 + DataGlobalConstants::KelvinConv}; // Kelvins
895 1770 : auto solarRadiation{0.}; // W/m2
896 1770 : if (useSummerConditions) {
897 : // NFRC 200 Section 4.3.1
898 463 : airTemperature = 32.0 + DataGlobalConstants::KelvinConv;
899 463 : airSpeed = 2.75;
900 463 : tSky = 32.0 + DataGlobalConstants::KelvinConv;
901 463 : solarRadiation = 783.;
902 : }
903 : auto Outdoor =
904 3540 : Tarcog::ISO15099::Environments::outdoor(airTemperature, airSpeed, solarRadiation, tSky, Tarcog::ISO15099::SkyModel::AllSpecified);
905 1770 : Outdoor->setHCoeffModel(Tarcog::ISO15099::BoundaryConditionsCoeffModel::CalculateH);
906 3540 : return Outdoor;
907 : }
908 :
909 1770 : std::shared_ptr<Tarcog::ISO15099::CEnvironment> CWCEHeatTransferFactory::getIndoorNfrc(bool const useSummerConditions)
910 : {
911 : // NFRC 100 Section 4.3.1
912 1770 : auto roomTemperature{21. + DataGlobalConstants::KelvinConv};
913 1770 : if (useSummerConditions) {
914 : // NFRC 200 Section 4.3.1
915 463 : roomTemperature = 24. + DataGlobalConstants::KelvinConv;
916 : }
917 3540 : auto Indoor = Tarcog::ISO15099::Environments::indoor(roomTemperature);
918 3540 : return Indoor;
919 : }
920 :
921 7296 : WinShadingType CWCEHeatTransferFactory::getShadeType(EnergyPlusData &state, int ConstrNum)
922 : {
923 7296 : WinShadingType ShadeFlag{WinShadingType::NoShade};
924 :
925 7296 : const auto TotLay = state.dataConstruction->Construct(ConstrNum).TotLayers;
926 7296 : const auto TotGlassLay = state.dataConstruction->Construct(ConstrNum).TotGlassLayers;
927 7296 : const auto MatOutside = state.dataConstruction->Construct(ConstrNum).LayerPoint(1);
928 7296 : const auto MatInside = state.dataConstruction->Construct(ConstrNum).LayerPoint(TotLay);
929 :
930 7296 : if (state.dataMaterial->Material(MatOutside).Group == DataHeatBalance::MaterialGroup::Shade) { // Exterior shade present
931 18 : ShadeFlag = WinShadingType::ExtShade;
932 7278 : } else if (state.dataMaterial->Material(MatOutside).Group == DataHeatBalance::MaterialGroup::Screen) { // Exterior screen present
933 0 : const auto MatShade = MatOutside;
934 0 : const auto ScNum = state.dataMaterial->Material(MatShade).ScreenDataPtr;
935 : // Orphaned constructs with exterior screen are ignored
936 0 : if (ScNum > 0) ShadeFlag = WinShadingType::ExtScreen;
937 7278 : } else if (state.dataMaterial->Material(MatOutside).Group == DataHeatBalance::MaterialGroup::WindowBlind) { // Exterior blind present
938 0 : ShadeFlag = WinShadingType::ExtBlind;
939 7278 : } else if (state.dataMaterial->Material(MatInside).Group == DataHeatBalance::MaterialGroup::Shade) { // Interior shade present
940 2778 : ShadeFlag = WinShadingType::IntShade;
941 4500 : } else if (state.dataMaterial->Material(MatInside).Group == DataHeatBalance::MaterialGroup::WindowBlind) { // Interior blind present
942 2688 : ShadeFlag = WinShadingType::IntBlind;
943 1812 : } else if (TotGlassLay == 2) {
944 1645 : if (state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNum).LayerPoint(3)).Group ==
945 : DataHeatBalance::MaterialGroup::Shade)
946 0 : ShadeFlag = WinShadingType::BGShade;
947 1645 : if (state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNum).LayerPoint(3)).Group ==
948 : DataHeatBalance::MaterialGroup::WindowBlind)
949 3 : ShadeFlag = WinShadingType::BGBlind;
950 167 : } else if (TotGlassLay == 3) {
951 2 : if (state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNum).LayerPoint(5)).Group ==
952 : DataHeatBalance::MaterialGroup::Shade)
953 0 : ShadeFlag = WinShadingType::BGShade;
954 2 : if (state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNum).LayerPoint(5)).Group ==
955 : DataHeatBalance::MaterialGroup::WindowBlind)
956 0 : ShadeFlag = WinShadingType::BGBlind;
957 : }
958 :
959 7296 : return ShadeFlag;
960 : }
961 :
962 1688 : double CWCEHeatTransferFactory::overallUfactorFromFilmsAndCond(double conductance, double insideFilm, double outsideFilm)
963 : {
964 1688 : double rOverall(0.);
965 1688 : double uFactor(0.);
966 1688 : if (insideFilm != 0 && outsideFilm != 0. && conductance != 0.) {
967 532 : rOverall = 1 / insideFilm + 1 / conductance + 1 / outsideFilm;
968 : }
969 1688 : if (rOverall != 0.) {
970 532 : uFactor = 1 / rOverall;
971 : }
972 1688 : return uFactor;
973 : }
974 :
975 : } // namespace WindowManager
976 2313 : } // namespace EnergyPlus
|