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 : #include <cassert>
49 :
50 : // EnergyPlus headers
51 : #include <EnergyPlus/Construction.hh>
52 : #include <EnergyPlus/Data/EnergyPlusData.hh>
53 : #include <EnergyPlus/DataEnvironment.hh>
54 : #include <EnergyPlus/DataHeatBalance.hh>
55 : #include <EnergyPlus/DataSurfaces.hh>
56 : #include <EnergyPlus/Material.hh>
57 : #include <EnergyPlus/WindowManager.hh>
58 :
59 : // Windows library headers
60 : #include <WCEMultiLayerOptics.hpp>
61 :
62 : #include "WindowManagerExteriorData.hh"
63 : #include "WindowManagerExteriorOptical.hh"
64 :
65 : namespace EnergyPlus {
66 :
67 : using namespace FenestrationCommon;
68 : using namespace SpectralAveraging;
69 : using namespace SingleLayerOptics;
70 :
71 : using namespace DataEnvironment;
72 : using namespace DataSurfaces;
73 : using namespace DataHeatBalance;
74 : namespace Window {
75 :
76 0 : std::shared_ptr<CBSDFLayer> getBSDFLayer(EnergyPlusData &state, const Material::MaterialChild &t_Material, const WavelengthRange t_Range)
77 : {
78 : // SUBROUTINE INFORMATION:
79 : // AUTHOR Simon Vidanovic
80 : // DATE WRITTEN September 2016
81 : // MODIFIED na
82 : // RE-ENGINEERED na
83 :
84 : // PURPOSE OF THIS SUBROUTINE:
85 : // BSDF will be created in different ways that is based on material type
86 :
87 0 : std::shared_ptr<CWCELayerFactory> aFactory = nullptr;
88 0 : if (t_Material.group == Material::Group::WindowGlass) {
89 0 : aFactory = std::make_shared<CWCESpecularLayerFactory>(t_Material, t_Range);
90 0 : } else if (t_Material.group == Material::Group::WindowBlind) {
91 0 : aFactory = std::make_shared<CWCEVenetianBlindLayerFactory>(t_Material, t_Range);
92 0 : } else if (t_Material.group == Material::Group::Screen) {
93 0 : aFactory = std::make_shared<CWCEScreenLayerFactory>(t_Material, t_Range);
94 0 : } else if (t_Material.group == Material::Group::Shade) {
95 0 : aFactory = std::make_shared<CWCEDiffuseShadeLayerFactory>(t_Material, t_Range);
96 : }
97 0 : return aFactory->getBSDFLayer(state);
98 0 : }
99 :
100 16 : CScatteringLayer getScatteringLayer(EnergyPlusData &state, const Material::MaterialChild &t_Material, const WavelengthRange t_Range)
101 : {
102 : // SUBROUTINE INFORMATION:
103 : // AUTHOR Simon Vidanovic
104 : // DATE WRITTEN May 2017
105 : // MODIFIED na
106 : // RE-ENGINEERED
107 : // April 2021: returning CScatteringLayer instead of pointer to it
108 :
109 : // PURPOSE OF THIS SUBROUTINE:
110 : // Scattering will be created in different ways that is based on material type
111 :
112 16 : std::shared_ptr<CWCELayerFactory> aFactory = nullptr;
113 16 : if (t_Material.group == Material::Group::WindowGlass || t_Material.group == Material::Group::WindowSimpleGlazing) {
114 12 : aFactory = std::make_shared<CWCESpecularLayerFactory>(t_Material, t_Range);
115 4 : } else if (t_Material.group == Material::Group::WindowBlind) {
116 2 : aFactory = std::make_shared<CWCEVenetianBlindLayerFactory>(t_Material, t_Range);
117 2 : } else if (t_Material.group == Material::Group::Screen) {
118 0 : aFactory = std::make_shared<CWCEScreenLayerFactory>(t_Material, t_Range);
119 2 : } else if (t_Material.group == Material::Group::Shade) {
120 2 : aFactory = std::make_shared<CWCEDiffuseShadeLayerFactory>(t_Material, t_Range);
121 : }
122 32 : return aFactory->getLayer(state);
123 16 : }
124 :
125 : // void InitWCE_BSDFOpticalData() {
126 : // // SUBROUTINE INFORMATION:
127 : // // AUTHOR Simon Vidanovic
128 : // // DATE WRITTEN September 2016
129 : // // MODIFIED na
130 : // // RE-ENGINEERED na
131 : //
132 : // // PURPOSE OF THIS SUBROUTINE:
133 : // // Initialize BSDF construction layers in Solar and Visible spectrum.
134 : //
135 : // auto aWinConstBSDF = CWindowConstructionsBSDF::instance();
136 : // for ( auto ConstrNum = 1; ConstrNum <= TotConstructs; ++ConstrNum ) {
137 : // auto& construction( Construct( ConstrNum ) );
138 : // if ( construction.isGlazingConstruction() ) {
139 : // for ( auto LayNum = 1; LayNum <= construction.TotLayers; ++LayNum ) {
140 : // auto& material( dataMaterial.Material( construction.LayerPoint( LayNum ) ) );
141 : // if ( material->group != WindowGas && material->group != WindowGasMixture &&
142 : // material->group != ComplexWindowGap && material->group != ComplexWindowShade ) {
143 : // auto aMaterial = std::make_shared< Material::MaterialBase >();
144 : // *aMaterial = material;
145 : //
146 : // // This is necessary because rest of EnergyPlus code relies on TransDiff property
147 : // // of construction. It will basically trigger Window optical calculations if this
148 : // // property is >0.
149 : // construction.TransDiff = 0.1;
150 : //
151 : // auto aRange = WavelengthRange::Solar;
152 : // auto aSolarLayer = getBSDFLayer( aMaterial, aRange );
153 : // aWinConstBSDF.pushBSDFLayer( aRange, ConstrNum, aSolarLayer );
154 : //
155 : // aRange = WavelengthRange::Visible;
156 : // auto aVisibleLayer = getBSDFLayer( aMaterial, aRange );
157 : // aWinConstBSDF.pushBSDFLayer( aRange, ConstrNum, aVisibleLayer );
158 : // }
159 : //
160 : // }
161 : // }
162 : // }
163 : // }
164 :
165 3 : void InitWCE_SimplifiedOpticalData(EnergyPlusData &state)
166 : {
167 : // SUBROUTINE INFORMATION:
168 : // AUTHOR Simon Vidanovic
169 : // DATE WRITTEN May 2017
170 : // MODIFIED na
171 : // RE-ENGINEERED na
172 :
173 : // PURPOSE OF THIS SUBROUTINE:
174 : // Initialize scattering construction layers in Solar and Visible spectrum.
175 :
176 : // Calculate optical properties of blind-type layers entered with MATERIAL:WindowBlind
177 : // Calculation from this is used for IR properties. Need to make sure that properties
178 : // are calculated with new WCE optical engine (for both blinds and screens)
179 3 : if (state.dataHeatBal->TotBlinds > 0) CalcWindowBlindProperties(state);
180 :
181 : // Initialize SurfaceScreen structure
182 3 : state.dataHeatBal->NumScreens = state.dataHeatBal->TotScreens;
183 3 : if (state.dataHeatBal->NumScreens > 0) CalcWindowScreenProperties(state);
184 :
185 3 : auto &aWinConstSimp = CWindowConstructionsSimplified::instance(state);
186 23 : for (int ConstrNum = 1; ConstrNum <= state.dataHeatBal->TotConstructs; ++ConstrNum) {
187 20 : auto &construction = state.dataConstruction->Construct(ConstrNum);
188 20 : if (construction.isGlazingConstruction(state)) {
189 14 : for (int LayNum = 1; LayNum <= construction.TotLayers; ++LayNum) {
190 9 : auto *materialBase(state.dataMaterial->Material(construction.LayerPoint(LayNum)));
191 9 : auto *material = dynamic_cast<Material::MaterialChild *>(materialBase);
192 9 : assert(material != nullptr);
193 9 : if (material->group != Material::Group::WindowGas && material->group != Material::Group::WindowGasMixture &&
194 9 : material->group != Material::Group::ComplexWindowGap && material->group != Material::Group::ComplexWindowShade) {
195 : // This is necessary because rest of EnergyPlus code relies on TransDiff property
196 : // of construction. It will basically trigger Window optical calculations if this
197 : // property is >0.
198 8 : construction.TransDiff = 0.1;
199 :
200 8 : WavelengthRange aRange = WavelengthRange::Solar;
201 8 : auto aSolarLayer = getScatteringLayer(state, *material, aRange); // (AUTO_OK_OBJ)
202 8 : aWinConstSimp.pushLayer(aRange, ConstrNum, aSolarLayer);
203 :
204 8 : aRange = WavelengthRange::Visible;
205 8 : auto aVisibleLayer = getScatteringLayer(state, *material, aRange); // (AUTO_OK_OBJ)
206 8 : aWinConstSimp.pushLayer(aRange, ConstrNum, aVisibleLayer);
207 8 : }
208 : }
209 : }
210 : }
211 :
212 : // Get effective glass and shade/blind emissivities for windows that have interior blind or
213 : // shade. These are used to calculate zone MRT contribution from window when
214 : // interior blind/shade is deployed.
215 :
216 24 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
217 21 : if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) continue;
218 21 : if (!state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).TypeIsWindow) continue;
219 3 : if (state.dataSurface->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) continue; // Irrelevant for Complex Fen
220 3 : if (state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).WindowTypeEQL) continue; // not required
221 3 : int ConstrNumSh = state.dataSurface->Surface(SurfNum).activeShadedConstruction;
222 3 : if (ConstrNumSh == 0) continue;
223 2 : int TotLay = state.dataConstruction->Construct(ConstrNumSh).TotLayers;
224 2 : bool IntShade = false;
225 2 : bool IntBlind = false;
226 2 : int ShadeLayPtr = 0;
227 2 : int BlNum = 0;
228 2 : auto const *thisMaterial = dynamic_cast<Material::MaterialChild *>(
229 2 : state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNumSh).LayerPoint(TotLay)));
230 2 : assert(thisMaterial != nullptr);
231 2 : if (thisMaterial->group == Material::Group::Shade) {
232 1 : IntShade = true;
233 1 : ShadeLayPtr = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(TotLay);
234 : }
235 2 : if (thisMaterial->group == Material::Group::WindowBlind) {
236 1 : IntBlind = true;
237 1 : BlNum = thisMaterial->BlindDataPtr;
238 : }
239 :
240 2 : if (IntShade || IntBlind) {
241 2 : for (int ISlatAng = 1; ISlatAng <= Material::MaxSlatAngs; ++ISlatAng) {
242 2 : Real64 EpsGlIR = 0.0;
243 2 : Real64 RhoGlIR = 0.0;
244 2 : if (IntShade || IntBlind) {
245 2 : EpsGlIR = dynamic_cast<const Material::MaterialChild *>(
246 2 : state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNumSh).LayerPoint(TotLay - 1)))
247 : ->AbsorpThermalBack;
248 2 : RhoGlIR = 1 - EpsGlIR;
249 : }
250 2 : if (IntShade) {
251 1 : auto const *thisMaterialShade = dynamic_cast<const Material::MaterialChild *>(state.dataMaterial->Material(ShadeLayPtr));
252 1 : Real64 TauShIR = thisMaterialShade->TransThermal;
253 1 : Real64 EpsShIR = thisMaterialShade->AbsorpThermal;
254 1 : Real64 RhoShIR = max(0.0, 1.0 - TauShIR - EpsShIR);
255 1 : state.dataSurface->SurfaceWindow(SurfNum).EffShBlindEmiss[1] =
256 1 : EpsShIR * (1.0 + RhoGlIR * TauShIR / (1.0 - RhoGlIR * RhoShIR));
257 1 : state.dataSurface->SurfaceWindow(SurfNum).EffGlassEmiss[1] = EpsGlIR * TauShIR / (1.0 - RhoGlIR * RhoShIR);
258 : }
259 2 : if (IntBlind) {
260 1 : Real64 TauShIR = state.dataMaterial->Blind(BlNum).IRFrontTrans(ISlatAng);
261 1 : Real64 EpsShIR = state.dataMaterial->Blind(BlNum).IRBackEmiss(ISlatAng);
262 1 : Real64 RhoShIR = max(0.0, 1.0 - TauShIR - EpsShIR);
263 1 : state.dataSurface->SurfaceWindow(SurfNum).EffShBlindEmiss[ISlatAng] =
264 1 : EpsShIR * (1.0 + RhoGlIR * TauShIR / (1.0 - RhoGlIR * RhoShIR));
265 1 : state.dataSurface->SurfaceWindow(SurfNum).EffGlassEmiss[ISlatAng] = EpsGlIR * TauShIR / (1.0 - RhoGlIR * RhoShIR);
266 : }
267 : // Loop over remaining slat angles only if blind with movable slats
268 2 : if (IntShade) break; // Loop over remaining slat angles only if blind
269 1 : if (IntBlind) {
270 1 : if (state.dataMaterial->Blind(BlNum).SlatAngleType == DataWindowEquivalentLayer::AngleType::Fixed) break;
271 : }
272 : } // End of slat angle loop
273 : } // End of check if interior shade or interior blind
274 : } // End of surface loop
275 3 : }
276 :
277 3 : Real64 GetSolarTransDirectHemispherical(EnergyPlusData &state, int ConstrNum)
278 : {
279 : const auto aWinConstSimp = // (AUTO_OK_SHARED_PTR)
280 3 : CWindowConstructionsSimplified::instance(state).getEquivalentLayer(state, FenestrationCommon::WavelengthRange::Solar, ConstrNum);
281 3 : return aWinConstSimp->getPropertySimple(
282 6 : 0.3, 2.5, FenestrationCommon::PropertySimple::T, FenestrationCommon::Side::Front, FenestrationCommon::Scattering::DirectHemispherical);
283 3 : }
284 :
285 3 : Real64 GetVisibleTransDirectHemispherical(EnergyPlusData &state, int ConstrNum)
286 : {
287 : const auto aWinConstSimp = // (AUTO_OK_SHARED_PTR)
288 3 : CWindowConstructionsSimplified::instance(state).getEquivalentLayer(state, FenestrationCommon::WavelengthRange::Visible, ConstrNum);
289 3 : return aWinConstSimp->getPropertySimple(
290 6 : 0.38, 0.78, FenestrationCommon::PropertySimple::T, FenestrationCommon::Side::Front, FenestrationCommon::Scattering::DirectHemispherical);
291 3 : }
292 :
293 : ///////////////////////////////////////////////////////////////////////////////
294 : // CWCEMaterialFactory
295 : ///////////////////////////////////////////////////////////////////////////////
296 16 : CWCEMaterialFactory::CWCEMaterialFactory(const Material::MaterialChild &t_Material, const WavelengthRange t_Range)
297 16 : : m_MaterialProperties(t_Material), m_Range(t_Range), m_Initialized(false)
298 : {
299 16 : }
300 :
301 16 : std::shared_ptr<CMaterial> CWCEMaterialFactory::getMaterial(EnergyPlusData &state)
302 : {
303 16 : if (!m_Initialized) {
304 16 : init(state);
305 16 : m_Initialized = true;
306 : }
307 16 : return m_Material;
308 : }
309 :
310 : ///////////////////////////////////////////////////////////////////////////////
311 : // CWCESpecularMaterialsFactory
312 : ///////////////////////////////////////////////////////////////////////////////
313 12 : CWCESpecularMaterialsFactory::CWCESpecularMaterialsFactory(const Material::MaterialChild &t_Material, const WavelengthRange t_Range)
314 12 : : CWCEMaterialFactory(t_Material, t_Range)
315 : {
316 12 : }
317 :
318 12 : void CWCESpecularMaterialsFactory::init(EnergyPlusData &state)
319 : {
320 12 : if (m_MaterialProperties.GlassSpectralDataPtr > 0) {
321 0 : auto aSolarSpectrum = CWCESpecturmProperties::getDefaultSolarRadiationSpectrum(state); // (AUTO_OK_OBJ)
322 0 : std::shared_ptr<CSpectralSampleData> aSampleData = nullptr;
323 0 : aSampleData = CWCESpecturmProperties::getSpectralSample(state, m_MaterialProperties.GlassSpectralDataPtr);
324 :
325 0 : auto aSample = std::make_shared<CSpectralSample>(aSampleData, aSolarSpectrum); // (AUTO_OK_SHARED_PTR)
326 :
327 0 : FenestrationCommon::MaterialType aType = MaterialType::Monolithic;
328 0 : CWavelengthRange aRange(m_Range);
329 0 : Real64 lowLambda = aRange.minLambda();
330 0 : Real64 highLambda = aRange.maxLambda();
331 :
332 : // Do not apply detector data if we do not have spectral data. This will only cause more inaccurate results at the end. (Simon)
333 0 : if (m_Range == WavelengthRange::Visible && m_MaterialProperties.GlassSpectralDataPtr != 0) {
334 0 : const auto aPhotopicResponse = CWCESpecturmProperties::getDefaultVisiblePhotopicResponse(state); // (AUTO_OK_OBJ)
335 0 : aSample->setDetectorData(aPhotopicResponse);
336 0 : }
337 :
338 0 : Real64 thickness = m_MaterialProperties.Thickness;
339 0 : m_Material = std::make_shared<CMaterialSample>(aSample, thickness, aType, lowLambda, highLambda);
340 0 : } else {
341 12 : if (m_Range == WavelengthRange::Solar) {
342 6 : m_Material = std::make_shared<CMaterialSingleBand>(m_MaterialProperties.Trans,
343 6 : m_MaterialProperties.Trans,
344 6 : m_MaterialProperties.ReflectSolBeamFront,
345 6 : m_MaterialProperties.ReflectSolBeamBack,
346 6 : m_Range);
347 : }
348 12 : if (m_Range == WavelengthRange::Visible) {
349 6 : m_Material = std::make_shared<CMaterialSingleBand>(m_MaterialProperties.TransVis,
350 6 : m_MaterialProperties.TransVis,
351 6 : m_MaterialProperties.ReflectVisBeamFront,
352 6 : m_MaterialProperties.ReflectVisBeamBack,
353 6 : m_Range);
354 : }
355 : }
356 12 : }
357 :
358 : ///////////////////////////////////////////////////////////////////////////////
359 : // CWCEMaterialDualBandFactory
360 : ///////////////////////////////////////////////////////////////////////////////
361 4 : CWCEMaterialDualBandFactory::CWCEMaterialDualBandFactory(const Material::MaterialChild &t_Material, const WavelengthRange t_Range)
362 4 : : CWCEMaterialFactory(t_Material, t_Range)
363 : {
364 4 : }
365 :
366 4 : void CWCEMaterialDualBandFactory::init([[maybe_unused]] EnergyPlusData &state)
367 : {
368 4 : if (m_Range == WavelengthRange::Visible) {
369 2 : m_Material = createVisibleRangeMaterial(state);
370 : } else {
371 2 : auto aVisibleRangeMaterial = createVisibleRangeMaterial(state); // (AUTO_OK_OBJ)
372 2 : auto aSolarRangeMaterial = createSolarRangeMaterial(state); // (AUTO_OK_OBJ)
373 : // Ratio visible to solar range. It can be calculated from solar spectrum.
374 2 : Real64 ratio = 0.49;
375 2 : m_Material = std::make_shared<CMaterialDualBand>(aVisibleRangeMaterial, aSolarRangeMaterial, ratio);
376 2 : }
377 4 : }
378 :
379 : ///////////////////////////////////////////////////////////////////////////////
380 : // CWCEVenetianBlindMaterialsFactory
381 : ///////////////////////////////////////////////////////////////////////////////
382 2 : CWCEVenetianBlindMaterialsFactory::CWCEVenetianBlindMaterialsFactory(const Material::MaterialChild &t_Material, 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 : int blindDataPtr = m_MaterialProperties.BlindDataPtr;
390 2 : assert(blindDataPtr > 0);
391 2 : auto &blind = state.dataMaterial->Blind(blindDataPtr);
392 :
393 2 : CWavelengthRange aRange(WavelengthRange::Visible);
394 2 : Real64 lowLambda = aRange.minLambda();
395 2 : Real64 highLambda = aRange.maxLambda();
396 :
397 2 : Real64 Tf = blind.SlatTransVisDiffDiff;
398 2 : Real64 Tb = blind.SlatTransVisDiffDiff;
399 2 : Real64 Rf = blind.SlatFrontReflVisDiffDiff;
400 2 : Real64 Rb = blind.SlatBackReflVisDiffDiff;
401 :
402 4 : return std::make_shared<CMaterialSingleBand>(Tf, Tb, Rf, Rb, lowLambda, highLambda);
403 2 : }
404 :
405 1 : std::shared_ptr<CMaterialSingleBand> CWCEVenetianBlindMaterialsFactory::createSolarRangeMaterial([[maybe_unused]] EnergyPlusData &state)
406 : {
407 1 : int blindDataPtr = m_MaterialProperties.BlindDataPtr;
408 1 : assert(blindDataPtr > 0);
409 1 : auto &blind = state.dataMaterial->Blind(blindDataPtr);
410 :
411 1 : CWavelengthRange aRange(WavelengthRange::Solar);
412 1 : Real64 lowLambda = aRange.minLambda();
413 1 : Real64 highLambda = aRange.maxLambda();
414 :
415 1 : Real64 Tf = blind.SlatTransSolDiffDiff;
416 1 : Real64 Tb = blind.SlatTransSolDiffDiff;
417 1 : Real64 Rf = blind.SlatFrontReflSolDiffDiff;
418 1 : Real64 Rb = blind.SlatBackReflSolDiffDiff;
419 :
420 2 : return std::make_shared<CMaterialSingleBand>(Tf, Tb, Rf, Rb, lowLambda, highLambda);
421 1 : }
422 :
423 : ///////////////////////////////////////////////////////////////////////////////
424 : // CWCEScreenMaterialsFactory
425 : ///////////////////////////////////////////////////////////////////////////////
426 0 : CWCEScreenMaterialsFactory::CWCEScreenMaterialsFactory(const Material::MaterialChild &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 : CWavelengthRange aRange(WavelengthRange::Visible);
436 0 : Real64 lowLambda = aRange.minLambda();
437 0 : Real64 highLambda = aRange.maxLambda();
438 :
439 0 : Real64 Tf = 0.0;
440 0 : Real64 Tb = 0.0;
441 0 : Real64 Rf = m_MaterialProperties.ReflectShadeVis;
442 0 : Real64 Rb = m_MaterialProperties.ReflectShadeVis;
443 :
444 0 : return std::make_shared<CMaterialSingleBand>(Tf, Tb, Rf, Rb, lowLambda, highLambda);
445 0 : }
446 :
447 0 : std::shared_ptr<CMaterialSingleBand> CWCEScreenMaterialsFactory::createSolarRangeMaterial([[maybe_unused]] EnergyPlusData &state)
448 : {
449 0 : CWavelengthRange aRange(WavelengthRange::Solar);
450 0 : Real64 lowLambda = aRange.minLambda();
451 0 : Real64 highLambda = aRange.maxLambda();
452 :
453 0 : Real64 Tf = 0.0;
454 0 : Real64 Tb = 0.0;
455 0 : Real64 Rf = m_MaterialProperties.ReflectShade;
456 0 : Real64 Rb = m_MaterialProperties.ReflectShade;
457 :
458 0 : return std::make_shared<CMaterialSingleBand>(Tf, Tb, Rf, Rb, lowLambda, highLambda);
459 0 : }
460 :
461 : ///////////////////////////////////////////////////////////////////////////////
462 : // CWCEDiffuseShadeMaterialsFactory
463 : ///////////////////////////////////////////////////////////////////////////////
464 2 : CWCEDiffuseShadeMaterialsFactory::CWCEDiffuseShadeMaterialsFactory(const Material::MaterialChild &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 2 : CWavelengthRange aRange(WavelengthRange::Visible);
472 2 : Real64 lowLambda = aRange.minLambda();
473 2 : Real64 highLambda = aRange.maxLambda();
474 :
475 2 : Real64 Tf = m_MaterialProperties.TransVis;
476 2 : Real64 Tb = m_MaterialProperties.TransVis;
477 2 : Real64 Rf = m_MaterialProperties.ReflectShadeVis;
478 2 : Real64 Rb = m_MaterialProperties.ReflectShadeVis;
479 :
480 4 : return std::make_shared<CMaterialSingleBand>(Tf, Tb, Rf, Rb, lowLambda, highLambda);
481 2 : }
482 :
483 1 : std::shared_ptr<CMaterialSingleBand> CWCEDiffuseShadeMaterialsFactory::createSolarRangeMaterial([[maybe_unused]] EnergyPlusData &state)
484 : {
485 1 : CWavelengthRange aRange(WavelengthRange::Solar);
486 1 : Real64 lowLambda = aRange.minLambda();
487 1 : Real64 highLambda = aRange.maxLambda();
488 :
489 1 : Real64 Tf = m_MaterialProperties.Trans;
490 1 : Real64 Tb = m_MaterialProperties.Trans;
491 1 : Real64 Rf = m_MaterialProperties.ReflectShade;
492 1 : Real64 Rb = m_MaterialProperties.ReflectShade;
493 :
494 2 : return std::make_shared<CMaterialSingleBand>(Tf, Tb, Rf, Rb, lowLambda, highLambda);
495 1 : }
496 :
497 : ///////////////////////////////////////////////////////////////////////////////
498 : // CWCECellFactory
499 : ///////////////////////////////////////////////////////////////////////////////
500 16 : IWCECellDescriptionFactory::IWCECellDescriptionFactory(const Material::MaterialChild &t_Material) : m_Material(t_Material)
501 : {
502 16 : }
503 :
504 : ///////////////////////////////////////////////////////////////////////////////
505 : // CWCESpecularCellFactory
506 : ///////////////////////////////////////////////////////////////////////////////
507 :
508 12 : CWCESpecularCellFactory::CWCESpecularCellFactory(const Material::MaterialChild &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::MaterialChild &t_Material) : IWCECellDescriptionFactory(t_Material)
521 : {
522 2 : }
523 :
524 2 : std::shared_ptr<ICellDescription> CWCEVenetianBlindCellFactory::getCellDescription([[maybe_unused]] EnergyPlusData &state)
525 : {
526 2 : const int blindDataPtr = m_Material.BlindDataPtr;
527 2 : assert(blindDataPtr > 0);
528 2 : auto &blind = state.dataMaterial->Blind(blindDataPtr);
529 :
530 2 : Real64 slatWidth = blind.SlatWidth;
531 2 : Real64 slatSpacing = blind.SlatSeparation;
532 2 : Real64 slatTiltAngle = 90.0 - blind.SlatAngle; // Need to convert to WCE system
533 2 : Real64 curvatureRadius = 0.0; // No curvature radius in current IDF definition
534 2 : size_t numOfSlatSegments = 5; // Number of segments to use in venetian calculations
535 2 : return std::make_shared<CVenetianCellDescription>(slatWidth, slatSpacing, slatTiltAngle, curvatureRadius, numOfSlatSegments);
536 : }
537 :
538 : ///////////////////////////////////////////////////////////////////////////////
539 : // CWCEScreenCellFactory
540 : ///////////////////////////////////////////////////////////////////////////////
541 0 : CWCEScreenCellFactory::CWCEScreenCellFactory(const Material::MaterialChild &t_Material) : IWCECellDescriptionFactory(t_Material)
542 : {
543 0 : }
544 :
545 0 : std::shared_ptr<ICellDescription> CWCEScreenCellFactory::getCellDescription([[maybe_unused]] EnergyPlusData &state)
546 : {
547 0 : Real64 diameter = m_Material.Thickness; // Thickness in this case is diameter
548 : // ratio is not saved withing material but rather calculated from transmittance
549 0 : const Real64 ratio = 1.0 - sqrt(m_Material.Trans);
550 0 : Real64 spacing = diameter / ratio;
551 0 : return std::make_shared<CWovenCellDescription>(diameter, spacing);
552 : }
553 :
554 : ///////////////////////////////////////////////////////////////////////////////
555 : // CWCEDiffuseShadeCellFactory
556 : ///////////////////////////////////////////////////////////////////////////////
557 2 : CWCEDiffuseShadeCellFactory::CWCEDiffuseShadeCellFactory(const Material::MaterialChild &t_Material) : IWCECellDescriptionFactory(t_Material)
558 : {
559 2 : }
560 :
561 2 : std::shared_ptr<ICellDescription> CWCEDiffuseShadeCellFactory::getCellDescription([[maybe_unused]] EnergyPlusData &state)
562 : {
563 2 : return std::make_shared<CFlatCellDescription>();
564 : }
565 :
566 : ///////////////////////////////////////////////////////////////////////////////
567 : // CWCEBSDFLayerFactory
568 : ///////////////////////////////////////////////////////////////////////////////
569 16 : CWCELayerFactory::CWCELayerFactory(const Material::MaterialChild &t_Material, const WavelengthRange t_Range)
570 16 : : m_Material(t_Material), m_Range(t_Range), m_BSDFInitialized(false), m_SimpleInitialized(false), m_MaterialFactory(nullptr)
571 : {
572 16 : }
573 :
574 16 : std::pair<std::shared_ptr<CMaterial>, std::shared_ptr<ICellDescription>> CWCELayerFactory::init(EnergyPlusData &state)
575 : {
576 16 : createMaterialFactory();
577 16 : auto aMaterial = m_MaterialFactory->getMaterial(state); // (AUTO_OK_SHARED_PTR)
578 16 : assert(aMaterial != nullptr);
579 16 : auto aCellDescription = getCellDescription(state); // (AUTO_OK_SHARED_PTR)
580 16 : assert(aCellDescription != nullptr);
581 :
582 32 : return std::make_pair(aMaterial, aCellDescription);
583 16 : }
584 :
585 0 : std::shared_ptr<CBSDFLayer> CWCELayerFactory::getBSDFLayer(EnergyPlusData &state)
586 : {
587 0 : if (!m_BSDFInitialized) {
588 0 : auto res = init(state); // (AUTO_OK_SHARED_PTR)
589 0 : const auto aBSDF = CBSDFHemisphere::create(BSDFBasis::Full); // (AUTO_OK_OBJ)
590 :
591 0 : CBSDFLayerMaker aMaker(res.first, aBSDF, res.second);
592 0 : m_BSDFLayer = aMaker.getLayer();
593 0 : m_BSDFInitialized = true;
594 0 : }
595 0 : return m_BSDFLayer;
596 : }
597 :
598 16 : CScatteringLayer CWCELayerFactory::getLayer(EnergyPlusData &state)
599 : {
600 16 : if (!m_SimpleInitialized) {
601 16 : auto res = init(state); // (AUTO_OK_SHARED_PTR)
602 :
603 16 : m_ScatteringLayer = CScatteringLayer(res.first, res.second);
604 16 : m_SimpleInitialized = true;
605 16 : }
606 16 : return m_ScatteringLayer;
607 : }
608 :
609 16 : std::shared_ptr<ICellDescription> CWCELayerFactory::getCellDescription([[maybe_unused]] EnergyPlusData &state) const
610 : {
611 16 : return m_CellFactory->getCellDescription(state);
612 : }
613 :
614 : ///////////////////////////////////////////////////////////////////////////////
615 : // CWCESpecularLayerFactory
616 : ///////////////////////////////////////////////////////////////////////////////
617 12 : CWCESpecularLayerFactory::CWCESpecularLayerFactory(const Material::MaterialChild &t_Material, const WavelengthRange t_Range)
618 12 : : CWCELayerFactory(t_Material, t_Range)
619 : {
620 12 : m_CellFactory = std::make_shared<CWCESpecularCellFactory>(t_Material);
621 12 : }
622 :
623 12 : void CWCESpecularLayerFactory::createMaterialFactory()
624 : {
625 12 : m_MaterialFactory = std::make_shared<CWCESpecularMaterialsFactory>(m_Material, m_Range);
626 12 : }
627 :
628 : ///////////////////////////////////////////////////////////////////////////////
629 : // CWCEVenetianBlindLayerFactory
630 : ///////////////////////////////////////////////////////////////////////////////
631 2 : CWCEVenetianBlindLayerFactory::CWCEVenetianBlindLayerFactory(const Material::MaterialChild &t_Material, const WavelengthRange t_Range)
632 2 : : CWCELayerFactory(t_Material, t_Range)
633 : {
634 2 : m_CellFactory = std::make_shared<CWCEVenetianBlindCellFactory>(t_Material);
635 2 : }
636 :
637 2 : void CWCEVenetianBlindLayerFactory::createMaterialFactory()
638 : {
639 2 : m_MaterialFactory = std::make_shared<CWCEVenetianBlindMaterialsFactory>(m_Material, m_Range);
640 2 : }
641 :
642 : ///////////////////////////////////////////////////////////////////////////////
643 : // CWCEScreenLayerFactory
644 : ///////////////////////////////////////////////////////////////////////////////
645 0 : CWCEScreenLayerFactory::CWCEScreenLayerFactory(const Material::MaterialChild &t_Material, const WavelengthRange t_Range)
646 0 : : CWCELayerFactory(t_Material, t_Range)
647 : {
648 0 : m_CellFactory = std::make_shared<CWCEScreenCellFactory>(t_Material);
649 0 : }
650 :
651 0 : void CWCEScreenLayerFactory::createMaterialFactory()
652 : {
653 0 : m_MaterialFactory = std::make_shared<CWCEScreenMaterialsFactory>(m_Material, m_Range);
654 0 : }
655 :
656 : ///////////////////////////////////////////////////////////////////////////////
657 : // CWCEDiffuseShadeLayerFactory
658 : ///////////////////////////////////////////////////////////////////////////////
659 2 : CWCEDiffuseShadeLayerFactory::CWCEDiffuseShadeLayerFactory(const Material::MaterialChild &t_Material, const WavelengthRange t_Range)
660 2 : : CWCELayerFactory(t_Material, t_Range)
661 : {
662 2 : m_CellFactory = std::make_shared<CWCEDiffuseShadeCellFactory>(t_Material);
663 2 : }
664 :
665 2 : void CWCEDiffuseShadeLayerFactory::createMaterialFactory()
666 : {
667 2 : m_MaterialFactory = std::make_shared<CWCEDiffuseShadeMaterialsFactory>(m_Material, m_Range);
668 2 : }
669 :
670 : } // namespace Window
671 : } // namespace EnergyPlus
|