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