Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : #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::MaterialBase *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::Glass) {
89 0 : aFactory = std::make_shared<CWCESpecularLayerFactory>(t_Material, t_Range);
90 0 : } else if (t_Material->group == Material::Group::Blind) {
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::MaterialBase *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::Glass || t_Material->group == Material::Group::GlassSimple) {
114 12 : aFactory = std::make_shared<CWCESpecularLayerFactory>(t_Material, t_Range);
115 4 : } else if (t_Material->group == Material::Group::Blind) {
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 : auto &s_mat = state.dataMaterial;
180 :
181 3 : if (s_mat->NumBlinds > 0) {
182 1 : CalcWindowBlindProperties(state);
183 : }
184 :
185 : // Initialize SurfaceScreen structure
186 3 : if (s_mat->NumScreens > 0) {
187 0 : CalcWindowScreenProperties(state);
188 : }
189 :
190 3 : auto &aWinConstSimp = CWindowConstructionsSimplified::instance(state);
191 23 : for (int ConstrNum = 1; ConstrNum <= state.dataHeatBal->TotConstructs; ++ConstrNum) {
192 20 : auto &construction = state.dataConstruction->Construct(ConstrNum);
193 20 : if (construction.isGlazingConstruction(state)) {
194 14 : for (int LayNum = 1; LayNum <= construction.TotLayers; ++LayNum) {
195 9 : auto const *mat = s_mat->materials(construction.LayerPoint(LayNum));
196 9 : if (mat->group != Material::Group::Gas && mat->group != Material::Group::GasMixture &&
197 9 : mat->group != Material::Group::ComplexWindowGap && mat->group != Material::Group::ComplexShade) {
198 : // This is necessary because rest of EnergyPlus code relies on TransDiff property
199 : // of construction. It will basically trigger Window optical calculations if this
200 : // property is >0.
201 8 : construction.TransDiff = 0.1;
202 :
203 8 : WavelengthRange aRange = WavelengthRange::Solar;
204 8 : auto aSolarLayer = getScatteringLayer(state, mat, aRange); // (AUTO_OK_OBJ)
205 8 : aWinConstSimp.pushLayer(aRange, ConstrNum, aSolarLayer);
206 :
207 8 : aRange = WavelengthRange::Visible;
208 8 : auto aVisibleLayer = getScatteringLayer(state, mat, aRange); // (AUTO_OK_OBJ)
209 8 : aWinConstSimp.pushLayer(aRange, ConstrNum, aVisibleLayer);
210 8 : }
211 : }
212 : }
213 : }
214 :
215 : // Get effective glass and shade/blind emissivities for windows that have interior blind or
216 : // shade. These are used to calculate zone MRT contribution from window when
217 : // interior blind/shade is deployed.
218 :
219 24 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
220 21 : auto &surf = state.dataSurface->Surface(SurfNum);
221 21 : auto &surfShade = state.dataSurface->surfShades(SurfNum);
222 :
223 21 : if (!surf.HeatTransSurf) {
224 0 : continue;
225 : }
226 21 : if (!state.dataConstruction->Construct(surf.Construction).TypeIsWindow) {
227 18 : continue;
228 : }
229 3 : if (state.dataSurface->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
230 0 : continue; // Irrelevant for Complex Fen
231 : }
232 3 : if (state.dataConstruction->Construct(surf.Construction).WindowTypeEQL) {
233 0 : continue; // not required
234 : }
235 :
236 3 : if (surf.activeShadedConstruction == 0) {
237 1 : continue;
238 : }
239 2 : auto &constrSh = state.dataConstruction->Construct(surf.activeShadedConstruction);
240 2 : int TotLay = constrSh.TotLayers;
241 2 : auto const *mat = s_mat->materials(constrSh.LayerPoint(TotLay));
242 :
243 2 : if (mat->group == Material::Group::Shade) {
244 1 : auto const *matShade = dynamic_cast<Material::MaterialShade const *>(mat);
245 1 : Real64 EpsGlIR = s_mat->materials(constrSh.LayerPoint(TotLay - 1))->AbsorpThermalBack;
246 1 : Real64 RhoGlIR = 1 - EpsGlIR;
247 1 : Real64 TauShIR = matShade->TransThermal;
248 1 : Real64 EpsShIR = matShade->AbsorpThermal;
249 1 : Real64 RhoShIR = max(0.0, 1.0 - TauShIR - EpsShIR);
250 1 : surfShade.effShadeEmi = EpsShIR * (1.0 + RhoGlIR * TauShIR / (1.0 - RhoGlIR * RhoShIR));
251 1 : surfShade.effGlassEmi = EpsGlIR * TauShIR / (1.0 - RhoGlIR * RhoShIR);
252 :
253 1 : } else if (mat->group == Material::Group::Blind) {
254 1 : Real64 EpsGlIR = s_mat->materials(constrSh.LayerPoint(TotLay - 1))->AbsorpThermalBack;
255 1 : Real64 RhoGlIR = 1 - EpsGlIR;
256 :
257 1 : auto const *matBlind = dynamic_cast<Material::MaterialBlind const *>(mat);
258 182 : for (int iSlatAng = 0; iSlatAng < Material::MaxSlatAngs; ++iSlatAng) {
259 181 : auto const &btar = matBlind->TARs[iSlatAng];
260 181 : Real64 TauShIR = btar.IR.Ft.Tra;
261 181 : Real64 EpsShIR = btar.IR.Ft.Emi;
262 181 : Real64 RhoShIR = max(0.0, 1.0 - TauShIR - EpsShIR);
263 181 : constrSh.effShadeBlindEmi[iSlatAng] = EpsShIR * (1.0 + RhoGlIR * TauShIR / (1.0 - RhoGlIR * RhoShIR));
264 181 : constrSh.effGlassEmi[iSlatAng] = EpsGlIR * TauShIR / (1.0 - RhoGlIR * RhoShIR);
265 : }
266 : // The following surface assignments previously lived in the WindowManagerExteriorThermal file.
267 : // They were moved here during the Material refactor, however I found that the array index values Lo/Hi
268 : // were making it here still as -1, and this was causing a difficult to diagnose segfault.
269 : // I'm moving these back over there, but open to suggestion if they need to be here.
270 : // surfShade.effShadeEmi = Interp(constrSh.effShadeBlindEmi[surfShade.blind.slatAngIdxLo],
271 : // constrSh.effShadeBlindEmi[surfShade.blind.slatAngIdxHi],
272 : // surfShade.blind.slatAngInterpFac);
273 : // surfShade.effGlassEmi = Interp(constrSh.effGlassEmi[surfShade.blind.slatAngIdxLo],
274 : // constrSh.effGlassEmi[surfShade.blind.slatAngIdxHi],
275 : // surfShade.blind.slatAngInterpFac);
276 : } // End of check if interior shade or interior blind
277 : } // End of surface loop
278 3 : } // InitWCE_SimplifiedOpticalData()
279 :
280 3 : Real64 GetSolarTransDirectHemispherical(EnergyPlusData &state, int ConstrNum)
281 : {
282 : const auto aWinConstSimp = // (AUTO_OK_SHARED_PTR)
283 3 : CWindowConstructionsSimplified::instance(state).getEquivalentLayer(state, FenestrationCommon::WavelengthRange::Solar, ConstrNum);
284 3 : return aWinConstSimp->getPropertySimple(
285 6 : 0.3, 2.5, FenestrationCommon::PropertySimple::T, FenestrationCommon::Side::Front, FenestrationCommon::Scattering::DirectHemispherical);
286 3 : }
287 :
288 3 : Real64 GetVisibleTransDirectHemispherical(EnergyPlusData &state, int ConstrNum)
289 : {
290 : const auto aWinConstSimp = // (AUTO_OK_SHARED_PTR)
291 3 : CWindowConstructionsSimplified::instance(state).getEquivalentLayer(state, FenestrationCommon::WavelengthRange::Visible, ConstrNum);
292 3 : return aWinConstSimp->getPropertySimple(
293 6 : 0.38, 0.78, FenestrationCommon::PropertySimple::T, FenestrationCommon::Side::Front, FenestrationCommon::Scattering::DirectHemispherical);
294 3 : }
295 :
296 : ///////////////////////////////////////////////////////////////////////////////
297 : // CWCEMaterialFactory
298 : ///////////////////////////////////////////////////////////////////////////////
299 16 : CWCEMaterialFactory::CWCEMaterialFactory(const Material::MaterialBase *t_Material, const WavelengthRange t_Range)
300 16 : : m_MaterialProperties(t_Material), m_Range(t_Range), m_Initialized(false)
301 : {
302 16 : }
303 :
304 16 : std::shared_ptr<CMaterial> CWCEMaterialFactory::getMaterial(EnergyPlusData &state)
305 : {
306 16 : if (!m_Initialized) {
307 16 : init(state);
308 16 : m_Initialized = true;
309 : }
310 16 : return m_Material;
311 : }
312 :
313 : ///////////////////////////////////////////////////////////////////////////////
314 : // CWCESpecularMaterialsFactory
315 : ///////////////////////////////////////////////////////////////////////////////
316 12 : CWCESpecularMaterialsFactory::CWCESpecularMaterialsFactory(const Material::MaterialBase *t_Material, const WavelengthRange t_Range)
317 12 : : CWCEMaterialFactory(t_Material, t_Range)
318 : {
319 12 : }
320 :
321 12 : void CWCESpecularMaterialsFactory::init(EnergyPlusData &state)
322 : {
323 12 : auto const *matGlass = dynamic_cast<Material::MaterialGlass const *>(m_MaterialProperties);
324 12 : assert(matGlass != nullptr);
325 :
326 12 : if (matGlass->GlassSpectralDataPtr > 0) {
327 0 : auto aSolarSpectrum = CWCESpecturmProperties::getDefaultSolarRadiationSpectrum(state); // (AUTO_OK_OBJ)
328 0 : std::shared_ptr<CSpectralSampleData> aSampleData = nullptr;
329 0 : aSampleData = CWCESpecturmProperties::getSpectralSample(state, matGlass->GlassSpectralDataPtr);
330 :
331 0 : auto aSample = std::make_shared<CSpectralSample>(aSampleData, aSolarSpectrum); // (AUTO_OK_SHARED_PTR)
332 :
333 0 : FenestrationCommon::MaterialType aType = MaterialType::Monolithic;
334 0 : CWavelengthRange aRange(m_Range);
335 0 : Real64 lowLambda = aRange.minLambda();
336 0 : Real64 highLambda = aRange.maxLambda();
337 :
338 : // Do not apply detector data if we do not have spectral data. This will only cause more inaccurate results at the end. (Simon)
339 0 : if (m_Range == WavelengthRange::Visible && matGlass->GlassSpectralDataPtr != 0) {
340 0 : const auto aPhotopicResponse = CWCESpecturmProperties::getDefaultVisiblePhotopicResponse(state); // (AUTO_OK_OBJ)
341 0 : aSample->setDetectorData(aPhotopicResponse);
342 0 : }
343 :
344 0 : Real64 thickness = matGlass->Thickness;
345 0 : m_Material = std::make_shared<CMaterialSample>(aSample, thickness, aType, lowLambda, highLambda);
346 0 : } else {
347 12 : if (m_Range == WavelengthRange::Solar) {
348 6 : m_Material = std::make_shared<CMaterialSingleBand>(
349 6 : matGlass->Trans, matGlass->Trans, matGlass->ReflectSolBeamFront, matGlass->ReflectSolBeamBack, m_Range);
350 : }
351 12 : if (m_Range == WavelengthRange::Visible) {
352 6 : m_Material = std::make_shared<CMaterialSingleBand>(
353 6 : matGlass->TransVis, matGlass->TransVis, matGlass->ReflectVisBeamFront, matGlass->ReflectVisBeamBack, m_Range);
354 : }
355 : }
356 12 : }
357 :
358 : ///////////////////////////////////////////////////////////////////////////////
359 : // CWCEMaterialDualBandFactory
360 : ///////////////////////////////////////////////////////////////////////////////
361 4 : CWCEMaterialDualBandFactory::CWCEMaterialDualBandFactory(const Material::MaterialBase *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::MaterialBase *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([[maybe_unused]] EnergyPlusData &state)
388 : {
389 2 : auto const *matBlind = dynamic_cast<Material::MaterialBlind const *>(m_MaterialProperties);
390 2 : assert(matBlind != nullptr);
391 :
392 2 : CWavelengthRange aRange(WavelengthRange::Visible);
393 2 : Real64 lowLambda = aRange.minLambda();
394 2 : Real64 highLambda = aRange.maxLambda();
395 :
396 2 : Real64 Tf = matBlind->slatTAR.Vis.Ft.Df.Tra;
397 2 : Real64 Tb = matBlind->slatTAR.Vis.Ft.Df.Tra;
398 2 : Real64 Rf = matBlind->slatTAR.Vis.Ft.Df.Ref;
399 2 : Real64 Rb = matBlind->slatTAR.Vis.Bk.Df.Ref;
400 :
401 4 : return std::make_shared<CMaterialSingleBand>(Tf, Tb, Rf, Rb, lowLambda, highLambda);
402 2 : }
403 :
404 1 : std::shared_ptr<CMaterialSingleBand> CWCEVenetianBlindMaterialsFactory::createSolarRangeMaterial([[maybe_unused]] EnergyPlusData &state)
405 : {
406 1 : auto const *matBlind = dynamic_cast<Material::MaterialBlind const *>(m_MaterialProperties);
407 1 : assert(matBlind != nullptr);
408 :
409 1 : CWavelengthRange aRange(WavelengthRange::Solar);
410 1 : Real64 lowLambda = aRange.minLambda();
411 1 : Real64 highLambda = aRange.maxLambda();
412 :
413 1 : Real64 Tf = matBlind->slatTAR.Sol.Ft.Df.Tra;
414 1 : Real64 Tb = matBlind->slatTAR.Sol.Ft.Df.Tra;
415 1 : Real64 Rf = matBlind->slatTAR.Sol.Ft.Df.Ref;
416 1 : Real64 Rb = matBlind->slatTAR.Sol.Bk.Df.Ref;
417 :
418 2 : return std::make_shared<CMaterialSingleBand>(Tf, Tb, Rf, Rb, lowLambda, highLambda);
419 1 : }
420 :
421 : ///////////////////////////////////////////////////////////////////////////////
422 : // CWCEScreenMaterialsFactory
423 : ///////////////////////////////////////////////////////////////////////////////
424 0 : CWCEScreenMaterialsFactory::CWCEScreenMaterialsFactory(const Material::MaterialBase *t_Material, const WavelengthRange t_Range)
425 0 : : CWCEMaterialDualBandFactory(t_Material, t_Range)
426 : {
427 : // Current EnergyPlus model does not support material transmittance different from zero.
428 : // To enable that, it would be necessary to change input in IDF
429 0 : }
430 :
431 0 : std::shared_ptr<CMaterialSingleBand> CWCEScreenMaterialsFactory::createVisibleRangeMaterial([[maybe_unused]] EnergyPlusData &state)
432 : {
433 0 : auto const *matShade = dynamic_cast<Material::MaterialShade const *>(m_MaterialProperties);
434 0 : assert(matShade != nullptr);
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 = matShade->ReflectShadeVis;
442 0 : Real64 Rb = matShade->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 : auto const *matShade = dynamic_cast<Material::MaterialShade const *>(m_MaterialProperties);
450 0 : assert(matShade != nullptr);
451 0 : CWavelengthRange aRange(WavelengthRange::Solar);
452 0 : Real64 lowLambda = aRange.minLambda();
453 0 : Real64 highLambda = aRange.maxLambda();
454 :
455 0 : Real64 Tf = 0.0;
456 0 : Real64 Tb = 0.0;
457 0 : Real64 Rf = matShade->ReflectShade;
458 0 : Real64 Rb = matShade->ReflectShade;
459 :
460 0 : return std::make_shared<CMaterialSingleBand>(Tf, Tb, Rf, Rb, lowLambda, highLambda);
461 0 : }
462 :
463 : ///////////////////////////////////////////////////////////////////////////////
464 : // CWCEDiffuseShadeMaterialsFactory
465 : ///////////////////////////////////////////////////////////////////////////////
466 2 : CWCEDiffuseShadeMaterialsFactory::CWCEDiffuseShadeMaterialsFactory(const Material::MaterialBase *t_Material, const WavelengthRange t_Range)
467 2 : : CWCEMaterialDualBandFactory(t_Material, t_Range)
468 : {
469 2 : }
470 :
471 2 : std::shared_ptr<CMaterialSingleBand> CWCEDiffuseShadeMaterialsFactory::createVisibleRangeMaterial([[maybe_unused]] EnergyPlusData &state)
472 : {
473 2 : auto const *matShade = dynamic_cast<Material::MaterialShade const *>(m_MaterialProperties);
474 2 : assert(matShade != nullptr);
475 2 : CWavelengthRange aRange(WavelengthRange::Visible);
476 2 : Real64 lowLambda = aRange.minLambda();
477 2 : Real64 highLambda = aRange.maxLambda();
478 :
479 2 : Real64 Tf = matShade->TransVis;
480 2 : Real64 Tb = matShade->TransVis;
481 2 : Real64 Rf = matShade->ReflectShadeVis;
482 2 : Real64 Rb = matShade->ReflectShadeVis;
483 :
484 4 : return std::make_shared<CMaterialSingleBand>(Tf, Tb, Rf, Rb, lowLambda, highLambda);
485 2 : }
486 :
487 1 : std::shared_ptr<CMaterialSingleBand> CWCEDiffuseShadeMaterialsFactory::createSolarRangeMaterial([[maybe_unused]] EnergyPlusData &state)
488 : {
489 1 : auto const *matShade = dynamic_cast<Material::MaterialShade const *>(m_MaterialProperties);
490 1 : assert(matShade != nullptr);
491 1 : CWavelengthRange aRange(WavelengthRange::Solar);
492 1 : Real64 lowLambda = aRange.minLambda();
493 1 : Real64 highLambda = aRange.maxLambda();
494 :
495 1 : Real64 Tf = matShade->Trans;
496 1 : Real64 Tb = matShade->Trans;
497 1 : Real64 Rf = matShade->ReflectShade;
498 1 : Real64 Rb = matShade->ReflectShade;
499 :
500 2 : return std::make_shared<CMaterialSingleBand>(Tf, Tb, Rf, Rb, lowLambda, highLambda);
501 1 : }
502 :
503 : ///////////////////////////////////////////////////////////////////////////////
504 : // CWCECellFactory
505 : ///////////////////////////////////////////////////////////////////////////////
506 16 : IWCECellDescriptionFactory::IWCECellDescriptionFactory(const Material::MaterialBase *t_Material) : m_Material(t_Material)
507 : {
508 16 : }
509 :
510 : ///////////////////////////////////////////////////////////////////////////////
511 : // CWCESpecularCellFactory
512 : ///////////////////////////////////////////////////////////////////////////////
513 :
514 12 : CWCESpecularCellFactory::CWCESpecularCellFactory(const Material::MaterialBase *t_Material) : IWCECellDescriptionFactory(t_Material)
515 : {
516 12 : }
517 :
518 12 : std::shared_ptr<ICellDescription> CWCESpecularCellFactory::getCellDescription([[maybe_unused]] EnergyPlusData &state)
519 : {
520 12 : return std::make_shared<CSpecularCellDescription>();
521 : }
522 :
523 : ///////////////////////////////////////////////////////////////////////////////
524 : // CWCEVenetianBlindCellFactory
525 : ///////////////////////////////////////////////////////////////////////////////
526 2 : CWCEVenetianBlindCellFactory::CWCEVenetianBlindCellFactory(const Material::MaterialBase *t_Material) : IWCECellDescriptionFactory(t_Material)
527 : {
528 2 : }
529 :
530 2 : std::shared_ptr<ICellDescription> CWCEVenetianBlindCellFactory::getCellDescription([[maybe_unused]] EnergyPlusData &state)
531 : {
532 2 : auto *matBlind = dynamic_cast<Material::MaterialBlind const *>(m_Material);
533 2 : assert(matBlind != nullptr);
534 :
535 2 : Real64 slatWidth = matBlind->SlatWidth;
536 2 : Real64 slatSpacing = matBlind->SlatSeparation;
537 2 : Real64 slatTiltAngle = 90.0 - matBlind->SlatAngle; // Need to convert to WCE system
538 2 : Real64 curvatureRadius = 0.0; // No curvature radius in current IDF definition
539 2 : size_t numOfSlatSegments = 5; // Number of segments to use in venetian calculations
540 2 : return std::make_shared<CVenetianCellDescription>(slatWidth, slatSpacing, slatTiltAngle, curvatureRadius, numOfSlatSegments);
541 : }
542 :
543 : ///////////////////////////////////////////////////////////////////////////////
544 : // CWCEScreenCellFactory
545 : ///////////////////////////////////////////////////////////////////////////////
546 0 : CWCEScreenCellFactory::CWCEScreenCellFactory(const Material::MaterialBase *t_Material) : IWCECellDescriptionFactory(t_Material)
547 : {
548 0 : }
549 :
550 0 : std::shared_ptr<ICellDescription> CWCEScreenCellFactory::getCellDescription([[maybe_unused]] EnergyPlusData &state)
551 : {
552 0 : Real64 diameter = m_Material->Thickness; // Thickness in this case is diameter
553 : // ratio is not saved withing material but rather calculated from transmittance
554 0 : const Real64 ratio = 1.0 - sqrt(dynamic_cast<Material::MaterialScreen const *>(m_Material)->Trans);
555 0 : Real64 spacing = diameter / ratio;
556 0 : return std::make_shared<CWovenCellDescription>(diameter, spacing);
557 : }
558 :
559 : ///////////////////////////////////////////////////////////////////////////////
560 : // CWCEDiffuseShadeCellFactory
561 : ///////////////////////////////////////////////////////////////////////////////
562 2 : CWCEDiffuseShadeCellFactory::CWCEDiffuseShadeCellFactory(const Material::MaterialBase *t_Material) : IWCECellDescriptionFactory(t_Material)
563 : {
564 2 : }
565 :
566 2 : std::shared_ptr<ICellDescription> CWCEDiffuseShadeCellFactory::getCellDescription([[maybe_unused]] EnergyPlusData &state)
567 : {
568 2 : return std::make_shared<CFlatCellDescription>();
569 : }
570 :
571 : ///////////////////////////////////////////////////////////////////////////////
572 : // CWCEBSDFLayerFactory
573 : ///////////////////////////////////////////////////////////////////////////////
574 16 : CWCELayerFactory::CWCELayerFactory(const Material::MaterialBase *t_Material, const WavelengthRange t_Range)
575 16 : : m_Material(t_Material), m_Range(t_Range), m_BSDFInitialized(false), m_SimpleInitialized(false), m_MaterialFactory(nullptr)
576 : {
577 16 : }
578 :
579 16 : std::pair<std::shared_ptr<CMaterial>, std::shared_ptr<ICellDescription>> CWCELayerFactory::init(EnergyPlusData &state)
580 : {
581 16 : createMaterialFactory();
582 16 : auto aMaterial = m_MaterialFactory->getMaterial(state); // (AUTO_OK_SHARED_PTR)
583 16 : assert(aMaterial != nullptr);
584 16 : auto aCellDescription = getCellDescription(state); // (AUTO_OK_SHARED_PTR)
585 16 : assert(aCellDescription != nullptr);
586 :
587 32 : return std::make_pair(aMaterial, aCellDescription);
588 16 : }
589 :
590 0 : std::shared_ptr<CBSDFLayer> CWCELayerFactory::getBSDFLayer(EnergyPlusData &state)
591 : {
592 0 : if (!m_BSDFInitialized) {
593 0 : auto res = init(state); // (AUTO_OK_SHARED_PTR)
594 0 : const auto aBSDF = CBSDFHemisphere::create(BSDFBasis::Full); // (AUTO_OK_OBJ)
595 :
596 0 : CBSDFLayerMaker aMaker(res.first, aBSDF, res.second);
597 0 : m_BSDFLayer = aMaker.getLayer();
598 0 : m_BSDFInitialized = true;
599 0 : }
600 0 : return m_BSDFLayer;
601 : }
602 :
603 16 : CScatteringLayer CWCELayerFactory::getLayer(EnergyPlusData &state)
604 : {
605 16 : if (!m_SimpleInitialized) {
606 16 : auto res = init(state); // (AUTO_OK_SHARED_PTR)
607 :
608 16 : m_ScatteringLayer = CScatteringLayer(res.first, res.second);
609 16 : m_SimpleInitialized = true;
610 16 : }
611 16 : return m_ScatteringLayer;
612 : }
613 :
614 16 : std::shared_ptr<ICellDescription> CWCELayerFactory::getCellDescription([[maybe_unused]] EnergyPlusData &state) const
615 : {
616 16 : return m_CellFactory->getCellDescription(state);
617 : }
618 :
619 : ///////////////////////////////////////////////////////////////////////////////
620 : // CWCESpecularLayerFactory
621 : ///////////////////////////////////////////////////////////////////////////////
622 12 : CWCESpecularLayerFactory::CWCESpecularLayerFactory(const Material::MaterialBase *t_Material, const WavelengthRange t_Range)
623 12 : : CWCELayerFactory(t_Material, t_Range)
624 : {
625 12 : m_CellFactory = std::make_shared<CWCESpecularCellFactory>(t_Material);
626 12 : }
627 :
628 12 : void CWCESpecularLayerFactory::createMaterialFactory()
629 : {
630 12 : m_MaterialFactory = std::make_shared<CWCESpecularMaterialsFactory>(m_Material, m_Range);
631 12 : }
632 :
633 : ///////////////////////////////////////////////////////////////////////////////
634 : // CWCEVenetianBlindLayerFactory
635 : ///////////////////////////////////////////////////////////////////////////////
636 2 : CWCEVenetianBlindLayerFactory::CWCEVenetianBlindLayerFactory(const Material::MaterialBase *t_Material, const WavelengthRange t_Range)
637 2 : : CWCELayerFactory(t_Material, t_Range)
638 : {
639 2 : m_CellFactory = std::make_shared<CWCEVenetianBlindCellFactory>(t_Material);
640 2 : }
641 :
642 2 : void CWCEVenetianBlindLayerFactory::createMaterialFactory()
643 : {
644 2 : m_MaterialFactory = std::make_shared<CWCEVenetianBlindMaterialsFactory>(m_Material, m_Range);
645 2 : }
646 :
647 : ///////////////////////////////////////////////////////////////////////////////
648 : // CWCEScreenLayerFactory
649 : ///////////////////////////////////////////////////////////////////////////////
650 0 : CWCEScreenLayerFactory::CWCEScreenLayerFactory(const Material::MaterialBase *t_Material, const WavelengthRange t_Range)
651 0 : : CWCELayerFactory(t_Material, t_Range)
652 : {
653 0 : m_CellFactory = std::make_shared<CWCEScreenCellFactory>(t_Material);
654 0 : }
655 :
656 0 : void CWCEScreenLayerFactory::createMaterialFactory()
657 : {
658 0 : m_MaterialFactory = std::make_shared<CWCEScreenMaterialsFactory>(m_Material, m_Range);
659 0 : }
660 :
661 : ///////////////////////////////////////////////////////////////////////////////
662 : // CWCEDiffuseShadeLayerFactory
663 : ///////////////////////////////////////////////////////////////////////////////
664 2 : CWCEDiffuseShadeLayerFactory::CWCEDiffuseShadeLayerFactory(const Material::MaterialBase *t_Material, const WavelengthRange t_Range)
665 2 : : CWCELayerFactory(t_Material, t_Range)
666 : {
667 2 : m_CellFactory = std::make_shared<CWCEDiffuseShadeCellFactory>(t_Material);
668 2 : }
669 :
670 2 : void CWCEDiffuseShadeLayerFactory::createMaterialFactory()
671 : {
672 2 : m_MaterialFactory = std::make_shared<CWCEDiffuseShadeMaterialsFactory>(m_Material, m_Range);
673 2 : }
674 :
675 : } // namespace Window
676 : } // namespace EnergyPlus
|