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