Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2023, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : #include <cassert>
49 :
50 : // EnergyPlus headers
51 : #include <EnergyPlus/BITF.hh>
52 : #include <EnergyPlus/Construction.hh>
53 : #include <EnergyPlus/Data/EnergyPlusData.hh>
54 : #include <EnergyPlus/DataEnvironment.hh>
55 : #include <EnergyPlus/DataHeatBalance.hh>
56 : #include <EnergyPlus/DataSurfaces.hh>
57 : #include <EnergyPlus/Material.hh>
58 : #include <EnergyPlus/WindowManager.hh>
59 :
60 : // Windows library headers
61 : #include <WCEMultiLayerOptics.hpp>
62 :
63 : #include "WindowManagerExteriorData.hh"
64 : #include "WindowManagerExteriorOptical.hh"
65 :
66 : namespace EnergyPlus {
67 :
68 : using namespace FenestrationCommon;
69 : using namespace SpectralAveraging;
70 : using namespace SingleLayerOptics;
71 :
72 : using namespace DataEnvironment;
73 : using namespace DataSurfaces;
74 : using namespace DataHeatBalance;
75 : namespace WindowManager {
76 :
77 0 : std::shared_ptr<CBSDFLayer> getBSDFLayer(EnergyPlusData &state, const Material::MaterialProperties &t_Material, const WavelengthRange t_Range)
78 : {
79 : // SUBROUTINE INFORMATION:
80 : // AUTHOR Simon Vidanovic
81 : // DATE WRITTEN September 2016
82 : // MODIFIED na
83 : // RE-ENGINEERED na
84 :
85 : // PURPOSE OF THIS SUBROUTINE:
86 : // BSDF will be created in different ways that is based on material type
87 :
88 0 : std::shared_ptr<CWCELayerFactory> aFactory = nullptr;
89 0 : if (t_Material.Group == DataHeatBalance::MaterialGroup::WindowGlass) {
90 0 : aFactory = std::make_shared<CWCESpecularLayerFactory>(t_Material, t_Range);
91 0 : } else if (t_Material.Group == DataHeatBalance::MaterialGroup::WindowBlind) {
92 0 : aFactory = std::make_shared<CWCEVenetianBlindLayerFactory>(t_Material, t_Range);
93 0 : } else if (t_Material.Group == DataHeatBalance::MaterialGroup::Screen) {
94 0 : aFactory = std::make_shared<CWCEScreenLayerFactory>(t_Material, t_Range);
95 0 : } else if (t_Material.Group == DataHeatBalance::MaterialGroup::Shade) {
96 0 : aFactory = std::make_shared<CWCEDiffuseShadeLayerFactory>(t_Material, t_Range);
97 : }
98 0 : return aFactory->getBSDFLayer(state);
99 : }
100 :
101 16 : CScatteringLayer getScatteringLayer(EnergyPlusData &state, const Material::MaterialProperties &t_Material, const WavelengthRange t_Range)
102 : {
103 : // SUBROUTINE INFORMATION:
104 : // AUTHOR Simon Vidanovic
105 : // DATE WRITTEN May 2017
106 : // MODIFIED na
107 : // RE-ENGINEERED
108 : // April 2021: returning CScatteringLayer instead of pointer to it
109 :
110 : // PURPOSE OF THIS SUBROUTINE:
111 : // Scattering will be created in different ways that is based on material type
112 :
113 32 : std::shared_ptr<CWCELayerFactory> aFactory = nullptr;
114 20 : if (t_Material.Group == DataHeatBalance::MaterialGroup::WindowGlass ||
115 4 : t_Material.Group == DataHeatBalance::MaterialGroup::WindowSimpleGlazing) {
116 12 : aFactory = std::make_shared<CWCESpecularLayerFactory>(t_Material, t_Range);
117 4 : } else if (t_Material.Group == DataHeatBalance::MaterialGroup::WindowBlind) {
118 2 : aFactory = std::make_shared<CWCEVenetianBlindLayerFactory>(t_Material, t_Range);
119 2 : } else if (t_Material.Group == DataHeatBalance::MaterialGroup::Screen) {
120 0 : aFactory = std::make_shared<CWCEScreenLayerFactory>(t_Material, t_Range);
121 2 : } else if (t_Material.Group == DataHeatBalance::MaterialGroup::Shade) {
122 2 : aFactory = std::make_shared<CWCEDiffuseShadeLayerFactory>(t_Material, t_Range);
123 : }
124 32 : return aFactory->getLayer(state);
125 : }
126 :
127 : // void InitWCE_BSDFOpticalData() {
128 : // // SUBROUTINE INFORMATION:
129 : // // AUTHOR Simon Vidanovic
130 : // // DATE WRITTEN September 2016
131 : // // MODIFIED na
132 : // // RE-ENGINEERED na
133 : //
134 : // // PURPOSE OF THIS SUBROUTINE:
135 : // // Initialize BSDF construction layers in Solar and Visible spectrum.
136 : //
137 : // auto aWinConstBSDF = CWindowConstructionsBSDF::instance();
138 : // for ( auto ConstrNum = 1; ConstrNum <= TotConstructs; ++ConstrNum ) {
139 : // auto& construction( Construct( ConstrNum ) );
140 : // if ( construction.isGlazingConstruction() ) {
141 : // for ( auto LayNum = 1; LayNum <= construction.TotLayers; ++LayNum ) {
142 : // auto& material( dataMaterial.Material( construction.LayerPoint( LayNum ) ) );
143 : // if ( material.Group != WindowGas && material.Group != WindowGasMixture &&
144 : // material.Group != ComplexWindowGap && material.Group != ComplexWindowShade ) {
145 : // auto aMaterial = std::make_shared< Material::MaterialProperties >();
146 : // *aMaterial = material;
147 : //
148 : // // This is necessary because rest of EnergyPlus code relies on TransDiff property
149 : // // of construction. It will basically trigger Window optical calculations if this
150 : // // property is >0.
151 : // construction.TransDiff = 0.1;
152 : //
153 : // auto aRange = WavelengthRange::Solar;
154 : // auto aSolarLayer = getBSDFLayer( aMaterial, aRange );
155 : // aWinConstBSDF.pushBSDFLayer( aRange, ConstrNum, aSolarLayer );
156 : //
157 : // aRange = WavelengthRange::Visible;
158 : // auto aVisibleLayer = getBSDFLayer( aMaterial, aRange );
159 : // aWinConstBSDF.pushBSDFLayer( aRange, ConstrNum, aVisibleLayer );
160 : // }
161 : //
162 : // }
163 : // }
164 : // }
165 : // }
166 :
167 3 : void InitWCE_SimplifiedOpticalData(EnergyPlusData &state)
168 : {
169 : // SUBROUTINE INFORMATION:
170 : // AUTHOR Simon Vidanovic
171 : // DATE WRITTEN May 2017
172 : // MODIFIED na
173 : // RE-ENGINEERED na
174 :
175 : // PURPOSE OF THIS SUBROUTINE:
176 : // Initialize scattering construction layers in Solar and Visible spectrum.
177 :
178 : // Calculate optical properties of blind-type layers entered with MATERIAL:WindowBlind
179 : // Calculation from this is used for IR properties. Need to make sure that properties
180 : // are calculated with new WCE optical engine (for both blinds and screens)
181 3 : if (state.dataHeatBal->TotBlinds > 0) CalcWindowBlindProperties(state);
182 :
183 : // Initialize SurfaceScreen structure
184 3 : state.dataHeatBal->NumSurfaceScreens = state.dataHeatBal->TotScreens;
185 3 : if (state.dataHeatBal->NumSurfaceScreens > 0) CalcWindowScreenProperties(state);
186 :
187 3 : auto &aWinConstSimp = CWindowConstructionsSimplified::instance();
188 23 : for (auto ConstrNum = 1; ConstrNum <= state.dataHeatBal->TotConstructs; ++ConstrNum) {
189 20 : auto &construction(state.dataConstruction->Construct(ConstrNum));
190 20 : if (construction.isGlazingConstruction(state)) {
191 14 : for (auto LayNum = 1; LayNum <= construction.TotLayers; ++LayNum) {
192 9 : auto &material(state.dataMaterial->Material(construction.LayerPoint(LayNum)));
193 9 : if (BITF_TEST_NONE(BITF(material.Group),
194 : BITF(DataHeatBalance::MaterialGroup::WindowGas) | BITF(DataHeatBalance::MaterialGroup::WindowGasMixture) |
195 : BITF(DataHeatBalance::MaterialGroup::ComplexWindowGap) |
196 : BITF(DataHeatBalance::MaterialGroup::ComplexWindowShade))) {
197 : // This is necessary because rest of EnergyPlus code relies on TransDiff property
198 : // of construction. It will basically trigger Window optical calculations if this
199 : // property is >0.
200 8 : construction.TransDiff = 0.1;
201 :
202 8 : auto aRange = WavelengthRange::Solar;
203 16 : auto aSolarLayer = getScatteringLayer(state, material, aRange);
204 8 : aWinConstSimp.pushLayer(aRange, ConstrNum, aSolarLayer);
205 :
206 8 : aRange = WavelengthRange::Visible;
207 16 : auto aVisibleLayer = getScatteringLayer(state, material, aRange);
208 8 : aWinConstSimp.pushLayer(aRange, ConstrNum, aVisibleLayer);
209 : }
210 : }
211 : }
212 : }
213 :
214 : // Get effective glass and shade/blind emissivities for windows that have interior blind or
215 : // shade. These are used to calculate zone MRT contribution from window when
216 : // interior blind/shade is deployed.
217 :
218 24 : for (auto SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
219 21 : if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) continue;
220 21 : if (!state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).TypeIsWindow) continue;
221 3 : if (state.dataSurface->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) continue; // Irrelevant for Complex Fen
222 3 : if (state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).WindowTypeEQL) continue; // not required
223 3 : auto ConstrNumSh = state.dataSurface->Surface(SurfNum).activeShadedConstruction;
224 3 : if (ConstrNumSh == 0) continue;
225 2 : auto TotLay = state.dataConstruction->Construct(ConstrNumSh).TotLayers;
226 2 : auto IntShade = false;
227 2 : auto IntBlind = false;
228 2 : auto ShadeLayPtr = 0;
229 2 : auto BlNum = 0;
230 2 : if (state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNumSh).LayerPoint(TotLay)).Group ==
231 : DataHeatBalance::MaterialGroup::Shade) {
232 1 : IntShade = true;
233 1 : ShadeLayPtr = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(TotLay);
234 : }
235 2 : if (state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNumSh).LayerPoint(TotLay)).Group ==
236 : DataHeatBalance::MaterialGroup::WindowBlind) {
237 1 : IntBlind = true;
238 1 : BlNum = state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNumSh).LayerPoint(TotLay)).BlindDataPtr;
239 : }
240 :
241 2 : if (IntShade || IntBlind) {
242 2 : for (auto ISlatAng = 1; ISlatAng <= MaxSlatAngs; ++ISlatAng) {
243 2 : auto EpsGlIR = 0.0;
244 2 : auto RhoGlIR = 0.0;
245 2 : if (IntShade || IntBlind) {
246 2 : EpsGlIR =
247 2 : state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNumSh).LayerPoint(TotLay - 1)).AbsorpThermalBack;
248 2 : RhoGlIR = 1 - EpsGlIR;
249 : }
250 2 : if (IntShade) {
251 1 : auto TauShIR = state.dataMaterial->Material(ShadeLayPtr).TransThermal;
252 1 : auto EpsShIR = state.dataMaterial->Material(ShadeLayPtr).AbsorpThermal;
253 1 : auto RhoShIR = max(0.0, 1.0 - TauShIR - EpsShIR);
254 1 : state.dataSurface->SurfaceWindow(SurfNum).EffShBlindEmiss(1) =
255 1 : EpsShIR * (1.0 + RhoGlIR * TauShIR / (1.0 - RhoGlIR * RhoShIR));
256 1 : state.dataSurface->SurfaceWindow(SurfNum).EffGlassEmiss(1) = EpsGlIR * TauShIR / (1.0 - RhoGlIR * RhoShIR);
257 : }
258 2 : if (IntBlind) {
259 1 : auto TauShIR = state.dataHeatBal->Blind(BlNum).IRFrontTrans(ISlatAng);
260 1 : auto EpsShIR = state.dataHeatBal->Blind(BlNum).IRBackEmiss(ISlatAng);
261 1 : auto RhoShIR = max(0.0, 1.0 - TauShIR - EpsShIR);
262 1 : state.dataSurface->SurfaceWindow(SurfNum).EffShBlindEmiss(ISlatAng) =
263 1 : EpsShIR * (1.0 + RhoGlIR * TauShIR / (1.0 - RhoGlIR * RhoShIR));
264 1 : state.dataSurface->SurfaceWindow(SurfNum).EffGlassEmiss(ISlatAng) = EpsGlIR * TauShIR / (1.0 - RhoGlIR * RhoShIR);
265 : }
266 : // Loop over remaining slat angles only if blind with movable slats
267 2 : if (IntShade) break; // Loop over remaining slat angles only if blind
268 1 : if (IntBlind) {
269 1 : if (state.dataHeatBal->Blind(BlNum).SlatAngleType == DataWindowEquivalentLayer::AngleType::Fixed) break;
270 : }
271 : } // End of slat angle loop
272 : } // End of check if interior shade or interior blind
273 : } // End of surface loop
274 3 : }
275 :
276 3 : Real64 GetSolarTransDirectHemispherical(EnergyPlusData &state, int ConstrNum)
277 : {
278 : const auto aWinConstSimp =
279 6 : CWindowConstructionsSimplified::instance().getEquivalentLayer(state, FenestrationCommon::WavelengthRange::Solar, ConstrNum);
280 3 : return aWinConstSimp->getPropertySimple(
281 6 : 0.3, 2.5, FenestrationCommon::PropertySimple::T, FenestrationCommon::Side::Front, FenestrationCommon::Scattering::DirectHemispherical);
282 : }
283 :
284 3 : Real64 GetVisibleTransDirectHemispherical(EnergyPlusData &state, int ConstrNum)
285 : {
286 : const auto aWinConstSimp =
287 6 : CWindowConstructionsSimplified::instance().getEquivalentLayer(state, FenestrationCommon::WavelengthRange::Visible, ConstrNum);
288 3 : return aWinConstSimp->getPropertySimple(
289 6 : 0.38, 0.78, FenestrationCommon::PropertySimple::T, FenestrationCommon::Side::Front, FenestrationCommon::Scattering::DirectHemispherical);
290 : }
291 :
292 : ///////////////////////////////////////////////////////////////////////////////
293 : // CWCEMaterialFactory
294 : ///////////////////////////////////////////////////////////////////////////////
295 16 : CWCEMaterialFactory::CWCEMaterialFactory(const Material::MaterialProperties &t_Material, const WavelengthRange t_Range)
296 16 : : m_MaterialProperties(t_Material), m_Range(t_Range), m_Initialized(false)
297 : {
298 16 : }
299 :
300 16 : std::shared_ptr<CMaterial> CWCEMaterialFactory::getMaterial(EnergyPlusData &state)
301 : {
302 16 : if (!m_Initialized) {
303 16 : init(state);
304 16 : m_Initialized = true;
305 : }
306 16 : return m_Material;
307 : }
308 :
309 : ///////////////////////////////////////////////////////////////////////////////
310 : // CWCESpecularMaterialsFactory
311 : ///////////////////////////////////////////////////////////////////////////////
312 12 : CWCESpecularMaterialsFactory::CWCESpecularMaterialsFactory(const Material::MaterialProperties &t_Material, const WavelengthRange t_Range)
313 12 : : CWCEMaterialFactory(t_Material, t_Range)
314 : {
315 12 : }
316 :
317 12 : void CWCESpecularMaterialsFactory::init(EnergyPlusData &state)
318 : {
319 12 : if (m_MaterialProperties.GlassSpectralDataPtr > 0) {
320 0 : auto aSolarSpectrum = CWCESpecturmProperties::getDefaultSolarRadiationSpectrum(state);
321 0 : std::shared_ptr<CSpectralSampleData> aSampleData = nullptr;
322 0 : aSampleData = CWCESpecturmProperties::getSpectralSample(state, m_MaterialProperties.GlassSpectralDataPtr);
323 :
324 0 : auto aSample = std::make_shared<CSpectralSample>(aSampleData, aSolarSpectrum);
325 :
326 0 : auto aType = MaterialType::Monolithic;
327 0 : auto aRange = CWavelengthRange(m_Range);
328 0 : auto lowLambda = aRange.minLambda();
329 0 : auto highLambda = aRange.maxLambda();
330 :
331 : // Do not apply detector data if we do not have spectral data. This will only cause more inaccurate results at the end. (Simon)
332 0 : if (m_Range == WavelengthRange::Visible && m_MaterialProperties.GlassSpectralDataPtr != 0) {
333 0 : const auto aPhotopicResponse = CWCESpecturmProperties::getDefaultVisiblePhotopicResponse(state);
334 0 : aSample->setDetectorData(aPhotopicResponse);
335 : }
336 :
337 0 : auto thickness = m_MaterialProperties.Thickness;
338 0 : m_Material = std::make_shared<CMaterialSample>(aSample, thickness, aType, lowLambda, highLambda);
339 : } else {
340 12 : if (m_Range == WavelengthRange::Solar) {
341 12 : m_Material = std::make_shared<CMaterialSingleBand>(m_MaterialProperties.Trans,
342 : m_MaterialProperties.Trans,
343 : m_MaterialProperties.ReflectSolBeamFront,
344 : m_MaterialProperties.ReflectSolBeamBack,
345 6 : m_Range);
346 : }
347 12 : if (m_Range == WavelengthRange::Visible) {
348 12 : m_Material = std::make_shared<CMaterialSingleBand>(m_MaterialProperties.TransVis,
349 : m_MaterialProperties.TransVis,
350 : m_MaterialProperties.ReflectVisBeamFront,
351 : m_MaterialProperties.ReflectVisBeamBack,
352 6 : m_Range);
353 : }
354 : }
355 12 : }
356 :
357 : ///////////////////////////////////////////////////////////////////////////////
358 : // CWCEMaterialDualBandFactory
359 : ///////////////////////////////////////////////////////////////////////////////
360 4 : CWCEMaterialDualBandFactory::CWCEMaterialDualBandFactory(const Material::MaterialProperties &t_Material, const WavelengthRange t_Range)
361 4 : : CWCEMaterialFactory(t_Material, t_Range)
362 : {
363 4 : }
364 :
365 4 : void CWCEMaterialDualBandFactory::init([[maybe_unused]] EnergyPlusData &state)
366 : {
367 4 : if (m_Range == WavelengthRange::Visible) {
368 2 : m_Material = createVisibleRangeMaterial(state);
369 : } else {
370 4 : auto aVisibleRangeMaterial = createVisibleRangeMaterial(state);
371 4 : auto aSolarRangeMaterial = createSolarRangeMaterial(state);
372 : // Ratio visible to solar range. It can be calculated from solar spectrum.
373 2 : auto ratio = 0.49;
374 2 : m_Material = std::make_shared<CMaterialDualBand>(aVisibleRangeMaterial, aSolarRangeMaterial, ratio);
375 : }
376 4 : }
377 :
378 : ///////////////////////////////////////////////////////////////////////////////
379 : // CWCEVenetianBlindMaterialsFactory
380 : ///////////////////////////////////////////////////////////////////////////////
381 2 : CWCEVenetianBlindMaterialsFactory::CWCEVenetianBlindMaterialsFactory(const Material::MaterialProperties &t_Material,
382 2 : const WavelengthRange t_Range)
383 2 : : CWCEMaterialDualBandFactory(t_Material, t_Range)
384 : {
385 2 : }
386 :
387 2 : std::shared_ptr<CMaterialSingleBand> CWCEVenetianBlindMaterialsFactory::createVisibleRangeMaterial(EnergyPlusData &state)
388 : {
389 2 : auto blindDataPtr = m_MaterialProperties.BlindDataPtr;
390 2 : auto &blind(state.dataHeatBal->Blind(blindDataPtr));
391 2 : assert(blindDataPtr > 0);
392 :
393 4 : auto aRange = CWavelengthRange(WavelengthRange::Visible);
394 2 : auto lowLambda = aRange.minLambda();
395 2 : auto highLambda = aRange.maxLambda();
396 :
397 2 : auto Tf = blind.SlatTransVisDiffDiff;
398 2 : auto Tb = blind.SlatTransVisDiffDiff;
399 2 : auto Rf = blind.SlatFrontReflVisDiffDiff;
400 2 : auto Rb = blind.SlatBackReflVisDiffDiff;
401 :
402 4 : return std::make_shared<CMaterialSingleBand>(Tf, Tb, Rf, Rb, lowLambda, highLambda);
403 : }
404 :
405 1 : std::shared_ptr<CMaterialSingleBand> CWCEVenetianBlindMaterialsFactory::createSolarRangeMaterial([[maybe_unused]] EnergyPlusData &state)
406 : {
407 1 : auto blindDataPtr = m_MaterialProperties.BlindDataPtr;
408 1 : auto &blind(state.dataHeatBal->Blind(blindDataPtr));
409 1 : assert(blindDataPtr > 0);
410 :
411 2 : auto aRange = CWavelengthRange(WavelengthRange::Solar);
412 1 : auto lowLambda = aRange.minLambda();
413 1 : auto highLambda = aRange.maxLambda();
414 :
415 1 : auto Tf = blind.SlatTransSolDiffDiff;
416 1 : auto Tb = blind.SlatTransSolDiffDiff;
417 1 : auto Rf = blind.SlatFrontReflSolDiffDiff;
418 1 : auto Rb = blind.SlatBackReflSolDiffDiff;
419 :
420 2 : return std::make_shared<CMaterialSingleBand>(Tf, Tb, Rf, Rb, lowLambda, highLambda);
421 : }
422 :
423 : ///////////////////////////////////////////////////////////////////////////////
424 : // CWCEScreenMaterialsFactory
425 : ///////////////////////////////////////////////////////////////////////////////
426 0 : CWCEScreenMaterialsFactory::CWCEScreenMaterialsFactory(const Material::MaterialProperties &t_Material, const WavelengthRange t_Range)
427 0 : : CWCEMaterialDualBandFactory(t_Material, t_Range)
428 : {
429 : // Current EnergyPlus model does not support material transmittance different from zero.
430 : // To enable that, it would be necessary to change input in IDF
431 0 : }
432 :
433 0 : std::shared_ptr<CMaterialSingleBand> CWCEScreenMaterialsFactory::createVisibleRangeMaterial([[maybe_unused]] EnergyPlusData &state)
434 : {
435 0 : auto aRange = CWavelengthRange(WavelengthRange::Visible);
436 0 : auto lowLambda = aRange.minLambda();
437 0 : auto highLambda = aRange.maxLambda();
438 :
439 0 : auto Tf = 0.0;
440 0 : auto Tb = 0.0;
441 0 : auto Rf = m_MaterialProperties.ReflectShadeVis;
442 0 : auto Rb = m_MaterialProperties.ReflectShadeVis;
443 :
444 0 : return std::make_shared<CMaterialSingleBand>(Tf, Tb, Rf, Rb, lowLambda, highLambda);
445 : }
446 :
447 0 : std::shared_ptr<CMaterialSingleBand> CWCEScreenMaterialsFactory::createSolarRangeMaterial([[maybe_unused]] EnergyPlusData &state)
448 : {
449 0 : auto aRange = CWavelengthRange(WavelengthRange::Solar);
450 0 : auto lowLambda = aRange.minLambda();
451 0 : auto highLambda = aRange.maxLambda();
452 :
453 0 : auto Tf = 0.0;
454 0 : auto Tb = 0.0;
455 0 : auto Rf = m_MaterialProperties.ReflectShade;
456 0 : auto Rb = m_MaterialProperties.ReflectShade;
457 :
458 0 : return std::make_shared<CMaterialSingleBand>(Tf, Tb, Rf, Rb, lowLambda, highLambda);
459 : }
460 :
461 : ///////////////////////////////////////////////////////////////////////////////
462 : // CWCEDiffuseShadeMaterialsFactory
463 : ///////////////////////////////////////////////////////////////////////////////
464 2 : CWCEDiffuseShadeMaterialsFactory::CWCEDiffuseShadeMaterialsFactory(const Material::MaterialProperties &t_Material, const WavelengthRange t_Range)
465 2 : : CWCEMaterialDualBandFactory(t_Material, t_Range)
466 : {
467 2 : }
468 :
469 2 : std::shared_ptr<CMaterialSingleBand> CWCEDiffuseShadeMaterialsFactory::createVisibleRangeMaterial([[maybe_unused]] EnergyPlusData &state)
470 : {
471 4 : auto aRange = CWavelengthRange(WavelengthRange::Visible);
472 2 : auto lowLambda = aRange.minLambda();
473 2 : auto highLambda = aRange.maxLambda();
474 :
475 2 : auto Tf = m_MaterialProperties.TransVis;
476 2 : auto Tb = m_MaterialProperties.TransVis;
477 2 : auto Rf = m_MaterialProperties.ReflectShadeVis;
478 2 : auto Rb = m_MaterialProperties.ReflectShadeVis;
479 :
480 4 : return std::make_shared<CMaterialSingleBand>(Tf, Tb, Rf, Rb, lowLambda, highLambda);
481 : }
482 :
483 1 : std::shared_ptr<CMaterialSingleBand> CWCEDiffuseShadeMaterialsFactory::createSolarRangeMaterial([[maybe_unused]] EnergyPlusData &state)
484 : {
485 2 : auto aRange = CWavelengthRange(WavelengthRange::Solar);
486 1 : auto lowLambda = aRange.minLambda();
487 1 : auto highLambda = aRange.maxLambda();
488 :
489 1 : auto Tf = m_MaterialProperties.Trans;
490 1 : auto Tb = m_MaterialProperties.Trans;
491 1 : auto Rf = m_MaterialProperties.ReflectShade;
492 1 : auto Rb = m_MaterialProperties.ReflectShade;
493 :
494 2 : return std::make_shared<CMaterialSingleBand>(Tf, Tb, Rf, Rb, lowLambda, highLambda);
495 : }
496 :
497 : ///////////////////////////////////////////////////////////////////////////////
498 : // CWCECellFactory
499 : ///////////////////////////////////////////////////////////////////////////////
500 16 : IWCECellDescriptionFactory::IWCECellDescriptionFactory(const Material::MaterialProperties &t_Material) : m_Material(t_Material)
501 : {
502 16 : }
503 :
504 : ///////////////////////////////////////////////////////////////////////////////
505 : // CWCESpecularCellFactory
506 : ///////////////////////////////////////////////////////////////////////////////
507 :
508 12 : CWCESpecularCellFactory::CWCESpecularCellFactory(const Material::MaterialProperties &t_Material) : IWCECellDescriptionFactory(t_Material)
509 : {
510 12 : }
511 :
512 12 : std::shared_ptr<ICellDescription> CWCESpecularCellFactory::getCellDescription([[maybe_unused]] EnergyPlusData &state)
513 : {
514 12 : return std::make_shared<CSpecularCellDescription>();
515 : }
516 :
517 : ///////////////////////////////////////////////////////////////////////////////
518 : // CWCEVenetianBlindCellFactory
519 : ///////////////////////////////////////////////////////////////////////////////
520 2 : CWCEVenetianBlindCellFactory::CWCEVenetianBlindCellFactory(const Material::MaterialProperties &t_Material)
521 2 : : IWCECellDescriptionFactory(t_Material)
522 : {
523 2 : }
524 :
525 2 : std::shared_ptr<ICellDescription> CWCEVenetianBlindCellFactory::getCellDescription([[maybe_unused]] EnergyPlusData &state)
526 : {
527 2 : const auto blindDataPtr = m_Material.BlindDataPtr;
528 2 : auto &blind(state.dataHeatBal->Blind(blindDataPtr));
529 2 : assert(blindDataPtr > 0);
530 :
531 2 : auto slatWidth = blind.SlatWidth;
532 2 : auto slatSpacing = blind.SlatSeparation;
533 2 : auto slatTiltAngle = 90 - blind.SlatAngle; // Need to convert to WCE system
534 2 : auto curvatureRadius = 0.0; // No curvature radius in current IDF definition
535 2 : size_t numOfSlatSegments = 5; // Number of segments to use in venetian calculations
536 2 : return std::make_shared<CVenetianCellDescription>(slatWidth, slatSpacing, slatTiltAngle, curvatureRadius, numOfSlatSegments);
537 : }
538 :
539 : ///////////////////////////////////////////////////////////////////////////////
540 : // CWCEScreenCellFactory
541 : ///////////////////////////////////////////////////////////////////////////////
542 0 : CWCEScreenCellFactory::CWCEScreenCellFactory(const Material::MaterialProperties &t_Material) : IWCECellDescriptionFactory(t_Material)
543 : {
544 0 : }
545 :
546 0 : std::shared_ptr<ICellDescription> CWCEScreenCellFactory::getCellDescription([[maybe_unused]] EnergyPlusData &state)
547 : {
548 0 : auto diameter = m_Material.Thickness; // Thickness in this case is diameter
549 : // ratio is not saved withing material but rather calculated from transmittance
550 0 : const auto ratio = 1.0 - sqrt(m_Material.Trans);
551 0 : auto spacing = diameter / ratio;
552 0 : return std::make_shared<CWovenCellDescription>(diameter, spacing);
553 : }
554 :
555 : ///////////////////////////////////////////////////////////////////////////////
556 : // CWCEDiffuseShadeCellFactory
557 : ///////////////////////////////////////////////////////////////////////////////
558 2 : CWCEDiffuseShadeCellFactory::CWCEDiffuseShadeCellFactory(const Material::MaterialProperties &t_Material) : IWCECellDescriptionFactory(t_Material)
559 : {
560 2 : }
561 :
562 2 : std::shared_ptr<ICellDescription> CWCEDiffuseShadeCellFactory::getCellDescription([[maybe_unused]] EnergyPlusData &state)
563 : {
564 2 : return std::make_shared<CFlatCellDescription>();
565 : }
566 :
567 : ///////////////////////////////////////////////////////////////////////////////
568 : // CWCEBSDFLayerFactory
569 : ///////////////////////////////////////////////////////////////////////////////
570 16 : CWCELayerFactory::CWCELayerFactory(const Material::MaterialProperties &t_Material, const WavelengthRange t_Range)
571 16 : : m_Material(t_Material), m_Range(t_Range), m_BSDFInitialized(false), m_SimpleInitialized(false), m_MaterialFactory(nullptr)
572 : {
573 16 : }
574 :
575 16 : std::pair<std::shared_ptr<CMaterial>, std::shared_ptr<ICellDescription>> CWCELayerFactory::init(EnergyPlusData &state)
576 : {
577 16 : createMaterialFactory();
578 32 : auto aMaterial = m_MaterialFactory->getMaterial(state);
579 16 : assert(aMaterial != nullptr);
580 32 : auto aCellDescription = getCellDescription(state);
581 16 : assert(aCellDescription != nullptr);
582 :
583 32 : return std::make_pair(aMaterial, aCellDescription);
584 : }
585 :
586 0 : std::shared_ptr<CBSDFLayer> CWCELayerFactory::getBSDFLayer(EnergyPlusData &state)
587 : {
588 0 : if (!m_BSDFInitialized) {
589 0 : auto res = init(state);
590 0 : const auto aBSDF = CBSDFHemisphere::create(BSDFBasis::Full);
591 :
592 0 : const auto aMaker = CBSDFLayerMaker(res.first, aBSDF, res.second);
593 0 : m_BSDFLayer = aMaker.getLayer();
594 0 : m_BSDFInitialized = true;
595 : }
596 0 : return m_BSDFLayer;
597 : }
598 :
599 16 : CScatteringLayer CWCELayerFactory::getLayer(EnergyPlusData &state)
600 : {
601 16 : if (!m_SimpleInitialized) {
602 32 : auto res = init(state);
603 :
604 16 : m_ScatteringLayer = CScatteringLayer(res.first, res.second);
605 16 : m_SimpleInitialized = true;
606 : }
607 16 : return m_ScatteringLayer;
608 : }
609 :
610 16 : std::shared_ptr<ICellDescription> CWCELayerFactory::getCellDescription([[maybe_unused]] EnergyPlusData &state) const
611 : {
612 16 : return m_CellFactory->getCellDescription(state);
613 : }
614 :
615 : ///////////////////////////////////////////////////////////////////////////////
616 : // CWCESpecularLayerFactory
617 : ///////////////////////////////////////////////////////////////////////////////
618 12 : CWCESpecularLayerFactory::CWCESpecularLayerFactory(const Material::MaterialProperties &t_Material, const WavelengthRange t_Range)
619 12 : : CWCELayerFactory(t_Material, t_Range)
620 : {
621 12 : m_CellFactory = std::make_shared<CWCESpecularCellFactory>(t_Material);
622 12 : }
623 :
624 12 : void CWCESpecularLayerFactory::createMaterialFactory()
625 : {
626 12 : m_MaterialFactory = std::make_shared<CWCESpecularMaterialsFactory>(m_Material, m_Range);
627 12 : }
628 :
629 : ///////////////////////////////////////////////////////////////////////////////
630 : // CWCEVenetianBlindLayerFactory
631 : ///////////////////////////////////////////////////////////////////////////////
632 2 : CWCEVenetianBlindLayerFactory::CWCEVenetianBlindLayerFactory(const Material::MaterialProperties &t_Material, const WavelengthRange t_Range)
633 2 : : CWCELayerFactory(t_Material, t_Range)
634 : {
635 2 : m_CellFactory = std::make_shared<CWCEVenetianBlindCellFactory>(t_Material);
636 2 : }
637 :
638 2 : void CWCEVenetianBlindLayerFactory::createMaterialFactory()
639 : {
640 2 : m_MaterialFactory = std::make_shared<CWCEVenetianBlindMaterialsFactory>(m_Material, m_Range);
641 2 : }
642 :
643 : ///////////////////////////////////////////////////////////////////////////////
644 : // CWCEScreenLayerFactory
645 : ///////////////////////////////////////////////////////////////////////////////
646 0 : CWCEScreenLayerFactory::CWCEScreenLayerFactory(const Material::MaterialProperties &t_Material, const WavelengthRange t_Range)
647 0 : : CWCELayerFactory(t_Material, t_Range)
648 : {
649 0 : m_CellFactory = std::make_shared<CWCEScreenCellFactory>(t_Material);
650 0 : }
651 :
652 0 : void CWCEScreenLayerFactory::createMaterialFactory()
653 : {
654 0 : m_MaterialFactory = std::make_shared<CWCEScreenMaterialsFactory>(m_Material, m_Range);
655 0 : }
656 :
657 : ///////////////////////////////////////////////////////////////////////////////
658 : // CWCEDiffuseShadeLayerFactory
659 : ///////////////////////////////////////////////////////////////////////////////
660 2 : CWCEDiffuseShadeLayerFactory::CWCEDiffuseShadeLayerFactory(const Material::MaterialProperties &t_Material, const WavelengthRange t_Range)
661 2 : : CWCELayerFactory(t_Material, t_Range)
662 : {
663 2 : m_CellFactory = std::make_shared<CWCEDiffuseShadeCellFactory>(t_Material);
664 2 : }
665 :
666 2 : void CWCEDiffuseShadeLayerFactory::createMaterialFactory()
667 : {
668 2 : m_MaterialFactory = std::make_shared<CWCEDiffuseShadeMaterialsFactory>(m_Material, m_Range);
669 2 : }
670 :
671 : } // namespace WindowManager
672 2313 : } // namespace EnergyPlus
|